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

С помощта на конкретни примери ще разгледаме възможностите за предаване на зависимости на презентатори и ще обясним методите и атрибутите/анотациите на inject.

inject*() Методи

В presenter, както и във всеки друг код, предпочитаният начин за предаване на зависимости е чрез използване на конструктор. Въпреки това, ако presenter наследява от общ предшественик (например BasePresenter), по-добре е да се използват методите на inject*() в този предшественик. Това е специален случай на setter, при който методът започва с префикс inject. Това е така, защото запазваме конструктора свободен за потомците:

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;
	}
}

Основната разлика от setter е, че Nette DI автоматично извиква методите с тези имена в preenters веднага след създаването на инстанцията, като им предава всички необходими зависимости. Презентаторът може да съдържа няколко метода inject*(), като всеки метод може да има произволен брой параметри.

Изпълнението чрез конструктор не се препоръчва за общи предци, тъй като по време на унаследяването трябва да получите зависимостите на всички родителски предци и да ги предадете на parent::__construct():

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
	private Foo $foo;

	public function __construct(Foo $foo)
	{
		$this->foo = $foo;
	}
}

class MyPresenter extends BasePresenter
{
	private Bar $bar;

	public function __construct(Foo $foo, Bar $bar)
	{
		parent::__construct($foo); // това е усложнение
		$this->bar = $bar;
	}
}

Методите inject*() са полезни и когато главният файл се състои от функции и всяка от тях изисква своя собствена зависимост.

Може да се използва и анотацията @inject, но е важно да се помни, че капсулирането е нарушено.

Анотации Inject

В този случай свойството е анотирано като @inject в коментара към документацията. Типът може да бъде анотиран и в коментара на документацията, ако използвате PHP под версия 7.4.

class MyPresenter extends Nette\Application\UI\Presenter
{
	/** @inject */
	public Cache $cache;
}

От версия PHP 8.0 свойството може да бъде маркирано с атрибута Inject:

use Nette\DI\Attributes\Inject;

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

Отново, Nette DI автоматично ще предава зависимости на свойствата, анотирани по този начин в презентатора, веднага щом инстанцията бъде създадена.

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