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.