Методи и атрибути за инжектиране

В тази статия ще се съсредоточим върху различните начини за предаване на зависимости на презентатори в рамката Nette. Ще сравним предпочитания метод, който е конструкторът, с други възможности, като например методи и атрибути на inject.

И за презентаторите предаването на зависимости чрез конструктора е предпочитаният начин. Въпреки това, ако създадете общ предшественик, от който другите презентатори наследяват (например BasePresenter), и този предшественик също има зависимости, възниква проблем, който наричаме конструкторски ад. Той може да бъде заобиколен с помощта на алтернативни методи, които включват инжектиране на методи и атрибути (анотации).

inject*() Методи

Това е форма на предаване на зависимости с помощта на задаващи елементи. Имената на тези задаващи елементи започват с префикса inject. Nette DI автоматично извиква тези методи веднага след създаването на инстанцията на презентатора и им предава всички необходими зависимости. Следователно те трябва да бъдат декларирани като публични.

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*() и всеки от тях може да има произволен брой параметри. Това е чудесно и за случаите, когато презентаторът е съставен от черти и всяка от тях изисква своя собствена зависимост.

Inject Атрибути

Това е форма на инжектиране в свойствата. Достатъчно е да посочите кои свойства трябва да бъдат инжектирани и Nette DI автоматично предава зависимостите веднага след създаването на инстанцията на презентатора. За да ги вмъкнете, е необходимо да ги декларирате като публични.

Свойствата се маркират с атрибут: (преди се използваше анотацията /** @inject */)

use Nette\DI\Attributes\Inject; // този ред е важен

class MyPresenter extends Nette\Application\UI\Presenter
{
	#[Inject]
	public Cache $cache;
}

Предимството на този метод за предаване на зависимостите е, че той е много икономичен за записване. С въвеждането на промоцията на свойствата на конструктора обаче използването на конструктора изглежда по-лесно.

От друга страна, този метод страда от същите недостатъци като предаването на зависимости в свойства като цяло: нямаме контрол върху промените в променливата, а в същото време променливата става част от публичния интерфейс на класа, което е нежелателно.