Методи и атрибути inject
В тази статия ще разгледаме различните начини за предаване на
зависимости към презентерите в Nette framework. Ще сравним предпочитания
начин, който е конструкторът, с други възможности като методите и
атрибутите inject
.
Също и за презентерите важи, че предаването на зависимости чрез конструктор
е предпочитаният път. Но ако създавате общ родител, от който наследяват
други презентери (напр. BasePresenter
), и този родител също има
зависимости, възниква проблем, който наричаме constructor hell. Той
може да бъде заобиколен чрез алтернативни пътища, които представляват
методите и атрибутите (анотациите) inject
.
Методи inject*()
Това е форма на предаване на зависимост чрез setter. Името на
тези сетъри започва с префикса inject
. Nette DI автоматично извиква
така наречените методи веднага след създаването на инстанцията на
презентера и им предава всички необходими зависимости. Следователно
те трябва да бъдат декларирани като public.
Методите inject*()
могат да се разглеждат като вид разширение на
конструктора в няколко метода. Благодарение на това BasePresenter
може да поеме зависимости чрез друг метод и да остави конструктора
свободен за своите наследници:
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;
}
}
Презентерът може да съдържа произволен брой методи inject*()
и
всеки може да има произволен брой параметри. Те са чудесни и в случаите,
когато презентерът е съставен от
trait и всеки от тях изисква собствена зависимост.
Атрибути Inject
Това е форма на инжектиране в свойство. Достатъчно е да се обозначи в кои променливи трябва да се инжектира и Nette DI автоматично ще предаде зависимостите веднага след създаването на инстанцията на презентера. За да може да ги вмъкне, е необходимо те да бъдат декларирани като public.
Означаваме свойствата с атрибут: (преди се използваше анотацията
/** @inject */
)
use Nette\DI\Attributes\Inject; // този ред е важен
class MyPresenter extends Nette\Application\UI\Presenter
{
#[Inject]
public Cache $cache;
}
Предимството на този начин на предаване на зависимости беше много икономичната форма на запис. Въпреки това, с появата на constructor property promotion, изглежда по-лесно да се използва конструктор.
От друга страна, този начин страда от същите недостатъци като предаването на зависимости към свойства като цяло: нямаме контрол над промените в променливата и същевременно променливата става част от публичния интерфейс на класа, което е нежелателно.