Model
Pe măsură ce aplicația noastră se dezvoltă, vom descoperi curând că trebuie să efectuăm operațiuni similare în baza de date în diferite locații și în diferite prezentări, de exemplu, achiziționarea celor mai noi articole publicate. Dacă ne îmbunătățim aplicația prin adăugarea unui indicator la articole pentru a indica o stare de lucru în curs de desfășurare, trebuie, de asemenea, să trecem prin toate locațiile din aplicația noastră și să adăugăm o clauză where pentru a ne asigura că sunt selectate numai articolele finalizate.
În acest moment, lucrul direct cu baza de date devine insuficient și va fi mai inteligent să ne ajutăm cu o nouă funcție care să returneze articolele publicate. Iar atunci când adăugăm o altă clauză mai târziu (de exemplu, pentru a nu afișa articolele cu o dată viitoare), vom edita codul nostru doar într-un singur loc.
Vom plasa funcția în clasa PostFacade
și o vom numi getPublicArticles()
.
Vom crea clasa noastră model PostFacade
în directorul app/Model/
pentru a avea grijă de articolele
noastre:
<?php
namespace App\Model;
use Nette;
final class PostFacade
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
public function getPublicArticles()
{
return $this->database
->table('posts')
->where('created_at < ', new \DateTime)
->order('created_at DESC');
}
}
În clasă vom trece baza de date Explorer. Acest lucru va profita de puterea containerului DI.
Vom trece la HomePresenter
pe care îl vom edita astfel încât să scăpăm de dependența de
Nette\Database\Explorer
înlocuind-o cu o nouă dependență de noua noastră clasă.
<?php
namespace App\UI\Home;
use App\Model\PostFacade;
use Nette;
final class HomePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private PostFacade $facade,
) {
}
public function renderDefault(): void
{
$this->template->posts = $this->facade
->getPublicArticles()
->limit(5);
}
}
În secțiunea de utilizare, folosim App\Model\PostFacade
, astfel încât putem scurta codul PHP la
PostFacade
. Solicităm acest obiect în constructor, îl scriem în proprietatea $facade
și îl folosim
în metoda renderDefault.
Ultimul pas rămas este să învățăm containerul DI să producă acest obiect. Acest lucru se face, de obicei, prin
adăugarea unui punct în fișierul config/services.neon
în secțiunea services
, oferind numele complet
al clasei și parametrii constructorului. Acest lucru îl înregistrează, ca să spunem așa, iar obiectul este apoi numit
service. Mulțumită unei magii numite autowiring,
de obicei nu este nevoie să specificăm parametrii constructorului, deoarece DI îi va recunoaște și îi va trece automat.
Astfel, ar fi suficient să furnizăm doar numele clasei:
...
services:
- App\Model\PostFacade
Cu toate acestea, nu este necesar să adăugați nici această linie. În secțiunea search
de la începutul
services.neon
este definit faptul că toate clasele care se termină cu -Facade
sau
-Factory
vor fi căutate automat de către DI, ceea ce este și cazul pentru PostFacade
.
Rezumat
Clasa PostFacade
solicită Nette\Database\Explorer
într-un constructor și, deoarece această clasă
este înregistrată în containerul DI, containerul creează această instanță și o transmite. În acest fel, DI creează
o instanță PostFacade
pentru noi și o transmite într-un constructor clasei HomePresenter care a cerut-o. Un fel
de păpușă Matryoshka de cod. :) Toate componentele solicită doar ceea ce au nevoie și nu le pasă unde și cum este creat.
Crearea este gestionată de containerul DI.
Aici puteți citi mai multe despre injecția de dependență și despre configurare.