Model
Ko aplikacija raste, bomo kmalu ugotovili, da na različnih mestih, v različnih presenterjih, potrebujemo izvajati podobne operacije s podatkovno bazo. Na primer pridobivati najnovejše objavljene članke. Ko aplikacijo izboljšamo, na primer tako, da pri člankih dodamo zastavico, ali je osnutek, moramo potem pregledati tudi vsa mesta v aplikaciji, kjer se članki pridobivajo iz podatkovne baze, in dopolniti pogoj where, da se izbirajo samo članki, ki niso osnutki.
V tistem trenutku neposredno delo s podatkovno bazo postane nezadostno in bo bolj priročno, če si pomagamo z novo funkcijo, ki nam bo vračala objavljene članke. In ko kasneje dodamo še en pogoj, na primer da se ne prikazujejo članki z datumom v prihodnosti, uredimo kodo samo na enem mestu.
Funkcijo postavimo na primer v razred PostFacade
in jo poimenujemo getPublicArticles()
.
V imeniku app/Model/
ustvarimo naš modelni razred PostFacade
, ki nam bo skrbel za članke:
<?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');
}
}
V razredu si s pomočjo konstruktorja pustimo predati podatkovni Explorer. Izkoristimo tako moč DI vsebnika.
Preklopimo na HomePresenter
, ki ga uredimo tako, da se znebimo odvisnosti od Nette\Database\Explorer
in jo nadomestimo z novo odvisnostjo od našega novega razreda.
<?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);
}
}
V sekciji use imamo App\Model\PostFacade
, tako da lahko zapis v PHP kodi skrajšamo na PostFacade
.
Za ta objekt zaprosimo v konstruktorju, ga zapišemo v lastnost $facade
in uporabimo v metodi renderDefault.
Ostaja še zadnji korak, in sicer naučiti DI vsebnik ta objekt izdelovati. To se običajno naredi tako, da v datoteko
config/services.neon
v sekcijo services
dodamo alinejo, navedemo polno ime razreda in parametre
konstruktorja. S tem ga tako imenovano registriramo in objekt se potem imenuje storitev. Zahvaljujoč čarovniji imenovani
autowiring nam večinoma ni treba navajati parametrov
konstruktorja, ker jih DI sam prepozna in preda. Zadostovalo bi torej navesti samo ime razreda:
...
services:
- App\Model\PostFacade
Vendar niti te vrstice ni treba dodajati. V sekciji search
na začetku services.neon
je definirano,
da vse razrede, ki se končajo z besedo -Facade
ali -Factory
, DI poišče sam, kar je tudi primer
PostFacade
.
Povzetek
Razred PostFacade
si v konstruktorju zahteva predajo Nette\Database\Explorer
in ker je ta razred
v DI vsebniku registriran, vsebnik to instanco ustvari in jo preda. DI za nas tako ustvari instanco PostFacade
in jo
preda v konstruktorju razredu HomePresenter, ki je zanjo zaprosil. Takšna matrjoška. :) Vsi si samo povedo, kaj želijo, in jih
ne zanima, kje se kaj in kako ustvarja. Za ustvarjanje skrbi DI vsebnik.
Tukaj si lahko preberete več o dependency injection in konfiguraciji.