Modell
Ahogy az alkalmazás növekszik, hamarosan rájövünk, hogy különböző helyeken, különböző presenterekben hasonló adatbázis-műveleteket kell végrehajtanunk. Például a legújabb publikált cikkek lekérése. Ha az alkalmazást például úgy fejlesztjük tovább, hogy a cikkeknél hozzáadunk egy jelzőt, hogy vázlatban van-e, akkor végig kell mennünk az alkalmazás összes olyan helyén, ahol cikkeket kérünk le az adatbázisból, és hozzá kell adnunk a where feltételt, hogy csak a nem vázlatban lévő cikkeket válasszuk ki.
Ebben a pillanatban a közvetlen adatbázis-munka elégtelenné válik, és ügyesebb lesz egy új funkcióval segíteni magunkon, amely a publikált cikkeket fogja visszaadni nekünk. És ha később hozzáadunk egy másik feltételt, például hogy ne jelenjenek meg a jövőbeli dátummal rendelkező cikkek, a kódot csak egy helyen módosítjuk.
A funkciót például a PostFacade
osztályba helyezzük, és getPublicArticles()
-nak
nevezzük el.
Az app/Model/
könyvtárban létrehozzuk a PostFacade
modell osztályunkat, amely a cikkekkel fog
foglalkozni:
<?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');
}
}
Az osztályban a konstruktor segítségével kérjük át az adatbázis Nette\Database\Explorer-t. Kihasználjuk a DI konténer erejét.
Váltsunk a HomePresenter
-re, amelyet úgy módosítunk, hogy megszabadulunk a
Nette\Database\Explorer
függőségtől, és lecseréljük az új osztályunktól való új függőségre.
<?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);
}
}
A use szakaszban App\Model\PostFacade
van, így a PHP kódban a jelölést lerövidíthetjük
PostFacade
-ra. Ezt az objektumot kérjük a konstruktorban, beírjuk a $facade
property-be, és
használjuk a renderDefault metódusban.
Már csak az utolsó lépés van hátra, megtanítani a DI konténert, hogy ezt az objektumot előállítsa. Ez általában
úgy történik, hogy a config/services.neon
fájl services
szakaszába hozzáadunk egy
felsorolásjelet, megadjuk az osztály teljes nevét és a konstruktor paramétereit. Ezzel regisztráljuk, és az objektumot
ezután szolgáltatásnak nevezzük. Az autowiring
nevű varázslatnak köszönhetően általában nem kell megadnunk a konstruktor paramétereit, mert a DI felismeri és átadja
őket. Így elegendő lenne csak az osztály nevét megadni:
...
services:
- App\Model\PostFacade
Azonban ezt a sort sem kell hozzáadnia. A services.neon
elején a search
szakaszban definiálva van,
hogy minden -Facade
vagy -Factory
végződésű osztályt a DI maga keres meg, ami a
PostFacade
esetében is így van.
Összegzés
A PostFacade
osztály a konstruktorában kéri a Nette\Database\Explorer
átadását, és mivel ez az
osztály regisztrálva van a DI konténerben, a konténer létrehozza ezt a példányt és átadja neki. A DI így létrehozza
nekünk a PostFacade
példányt, és átadja a konstruktorban a HomePresenter osztálynak, amely kérte. Ilyen
matrjoska. :) Mindenki csak megmondja, mit akar, és nem érdekli, hol és hogyan jön létre valami. A létrehozásról a DI
konténer gondoskodik.
Itt többet olvashat a dependency injection-ről és a konfigurációról.