Inject metódusok és attribútumok
Ebben a cikkben a függőségek Nette keretrendszerbeli presenterekbe történő átadásának különböző
módjaira összpontosítunk. Összehasonlítjuk az előnyben részesített módszert, amely a konstruktor, más lehetőségekkel,
mint például az inject
metódusok és attribútumok.
A presenterekre is igaz, hogy a függőségek konstruktoron
keresztüli átadása az előnyben részesített út. Ha azonban létrehozol egy közös őst, amelyből a többi presenter
öröklődik (pl. BasePresenter
), és ennek az ősnek is vannak függőségei, akkor egy problémába ütközünk,
amelyet constructor hell-nek
nevezünk. Ezt meg lehet kerülni alternatív utakkal, amelyeket az inject
metódusok és attribútumok (korábban
annotációk) jelentenek.
inject*()
metódusok
Ez a függőségátadás setterrel történő
formája. Ezeknek a settereknek a neve inject
előtaggal kezdődik. A Nette DI az így elnevezett metódusokat
automatikusan meghívja rögtön a presenter példányának létrehozása után, és átadja nekik az összes szükséges
függőséget. Ezért public-ként kell deklarálni őket.
Az inject*()
metódusok tekinthetők a konstruktor egyfajta kiterjesztésének több metódusba. Ennek
köszönhetően a BasePresenter
más metóduson keresztül veheti át a függőségeket, és a konstruktort szabadon
hagyhatja a leszármazottai számára:
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
private Foo $foo;
public function injectBase(Foo $foo): void
{
$this->foo = $foo;
}
}
class MyPresenter extends BasePresenter
{
private Bar $bar;
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
}
A presenter tetszőleges számú inject*()
metódust tartalmazhat, és mindegyiknek tetszőleges számú
paramétere lehet. Kiválóan alkalmasak olyan esetekben is, amikor a presenter traitekből áll össze, és mindegyik saját függőséget
igényel.
Inject
attribútumok
Ez a property-be történő injektálás formája. Elég megjelölni, hogy mely változókba kell injektálni, és a Nette DI automatikusan átadja a függőségeket rögtön a presenter példányának létrehozása után. Ahhoz, hogy be tudja illeszteni őket, public-ként kell deklarálni őket.
A property-ket attribútummal jelöljük meg: (korábban a /** @inject */
annotációt használták)
use Nette\DI\Attributes\Inject; // ez a sor fontos
class MyPresenter extends Nette\Application\UI\Presenter
{
#[Inject]
public Cache $cache;
}
Ennek a függőségátadási módnak az előnye a nagyon tömör írásmód volt. Azonban a constructor property promotion megjelenésével egyszerűbbnek tűnik a konstruktor használata.
Másrészt ez a módszer ugyanazoktól a hiányosságoktól szenved, mint a függőségek általános property-kbe történő átadása: nincs ellenőrzésünk a változóban bekövetkező változások felett, és ugyanakkor a változó az osztály nyilvános interfészének részévé válik, ami nem kívánatos.