Методы и атрибуты инъекции

На конкретных примерах мы рассмотрим возможности передачи зависимостей ведущим и объясним методы inject и атрибуты/аннотации.

inject*() Методы

В презентаторе, как и в любом другом коде, предпочтительным способом передачи зависимостей является использование конструктора. Однако если презентер наследуется от общего предка (например, BasePresenter), то лучше использовать методы inject*() в этом предке. Это особый случай сеттера, когда метод начинается с префикса 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;
	}
}

Основное отличие от сеттера заключается в том, что Nette DI автоматически вызывает методы с такими именами в презентерах сразу после создания экземпляра, передавая им все необходимые зависимости. Презентер может содержать несколько методов 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 автоматически передаст зависимости свойствам, аннотированным таким образом в презентере, как только экземпляр будет создан.

Этот метод имеет те же недостатки, что и передача зависимостей в публичное свойство. Он используется в презентерах, поскольку не усложняет код и требует минимального набора текста.