Metody i atrybuty wstrzykiwania
W tym artykule skupimy się na różnych sposobach przekazywania zależności do prezenterów w frameworku Nette.
Porównamy preferowaną metodę, jaką jest konstruktor, z innymi opcjami, takimi jak inject
metody i atrybuty.
Również dla prezenterów przekazywanie zależności za pomocą konstruktora jest preferowanym sposobem. Jednakże, jeśli stworzysz wspólnego przodka, z którego dziedziczą inne prezentery (np. BasePresenter), a ten przodek również posiada zależności, pojawia się problem, który nazywamy piekłem konstruktora. Można to obejść, stosując alternatywne metody, które obejmują metody wstrzykiwania i atrybuty (adnotacje).
Metody inject*()
Jest to forma przekazywania zależności za pomocą seterów. Nazwy tych seterów zaczynają się od przedrostka inject. Nette DI automatycznie wywołuje tak nazwane metody zaraz po utworzeniu instancji prezentera i przekazuje do nich wszystkie wymagane zależności. Dlatego muszą być one zadeklarowane jako publiczne.
inject*()
metody można uznać za rodzaj rozszerzenia konstruktora na wiele metod. Dzięki temu
BasePresenter
może przyjmować zależności poprzez inną metodę i pozostawić konstruktor wolny dla swoich
potomków:
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;
}
}
Prezenter może zawierać dowolną liczbę metod inject*()
, a każda z nich może mieć dowolną liczbę
parametrów. Jest to również świetne rozwiązanie dla przypadków, w których prezenter składa się z cech, a każda z nich wymaga własnej
zależności.
Inject
Atrybuty
Jest to forma wstrzyknięcia do właściwości. Wystarczy wskazać, które właściwości powinny zostać wstrzyknięte, a Nette DI automatycznie przekazuje zależności zaraz po utworzeniu instancji prezentera. Aby je wstawić, konieczne jest zadeklarowanie ich jako publicznych.
Właściwości oznaczane są atrybutem: (wcześniej używano adnotacji /** @inject */
)
use Nette\DI\Attributes\Inject; // ta linia jest ważna.
class MyPresenter extends Nette\Application\UI\Presenter
{
#[Inject]
public Cache $cache;
}
Zaletą tej metody przekazywania zależności była bardzo oszczędna forma notacji. Jednak po wprowadzeniu promocji właściwości konstruktora, korzystanie z konstruktora wydaje się łatwiejsze.
Z drugiej strony, metoda ta cierpi na te same wady, co przekazywanie zależności do właściwości w ogóle: nie mamy kontroli nad zmianami w zmiennej, a jednocześnie zmienna staje się częścią publicznego interfejsu klasy, co jest niepożądane.