Model
Pe măsură ce aplicația crește, vom descoperi curând că în diferite locuri, în diferiți presenteri, avem nevoie să efectuăm operații similare cu baza de date. De exemplu, să obținem cele mai recente articole publicate. Dacă îmbunătățim aplicația, de exemplu, adăugând un indicator la articole dacă sunt în curs de redactare, trebuie apoi să parcurgem toate locurile din aplicație unde se obțin articole din baza de date și să adăugăm condiția where, pentru a selecta doar articolele care nu sunt în curs de redactare.
În acel moment, lucrul direct cu baza de date devine insuficient și va fi mai inteligent să ne ajutăm cu o nouă funcție care ne va returna articolele publicate. Și dacă ulterior adăugăm o altă condiție, de exemplu, că nu trebuie afișate articolele cu dată viitoare, vom modifica codul doar într-un singur loc.
Vom plasa funcția, de exemplu, în clasa PostFacade
și o vom numi getPublicArticles()
.
În directorul app/Model/
vom crea clasa noastră de model PostFacade
, care se va ocupa de
articole:
<?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ă, prin intermediul constructorului, vom solicita transmiterea bazei de date Explorer. Vom folosi astfel puterea containerului DI.
Trecem la HomePresenter
, pe care îl vom modifica astfel încât să eliminăm dependența de
Nette\Database\Explorer
și să o înlocuim cu noua dependență de clasa noastră nouă.
<?php
namespace App\Presentation\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 use avem App\Model\PostFacade
, așa că putem scurta notația în codul PHP la
PostFacade
. Solicităm acest obiect în constructor, îl scriem în proprietatea $facade
și îl folosim
în metoda renderDefault.
Rămâne ultimul pas și anume să învățăm containerul DI să producă acest obiect. Acest lucru se face de obicei
adăugând un element cu bulină în fișierul config/services.neon
în secțiunea services
,
specificând numele complet al clasei și parametrii constructorului. Astfel o înregistrăm, iar obiectul se numește apoi
serviciu. Datorită magiei numite autowiring, de
cele mai multe ori nu trebuie să specificăm parametrii constructorului, deoarece DI îi recunoaște și îi transmite automat.
Ar fi suficient deci să specificăm doar numele clasei:
...
services:
- App\Model\PostFacade
Cu toate acestea, nici această linie nu trebuie adăugată. În secțiunea search
de la începutul
services.neon
este definit că toate clasele care se termină cu cuvântul -Facade
sau
-Factory
vor fi găsite automat de DI, ceea ce este și cazul PostFacade
.
Rezumat
Clasa PostFacade
solicită în constructor transmiterea Nette\Database\Explorer
și, deoarece
această clasă este înregistrată în containerul DI, containerul creează această instanță și o transmite. DI creează
astfel pentru noi instanța PostFacade
și o transmite în constructor clasei HomePresenter, care a solicitat-o. Un
fel de păpușă Matrioșka. :) Toată lumea spune doar ce vrea și nu se interesează unde și cum se creează ceva. De creare se
ocupă containerul DI.
Aici puteți citi mai multe despre injecția de dependențe și configurare.