Методи та атрибути ін'єкції

На конкретних прикладах ми розглянемо можливості передачі залежностей доповідачам і пояснимо методи та атрибути/анотації inject.

inject*() Методи

У presenter, як і в будь-якому іншому коді, найкращим способом передачі залежностей є використання конструктора. Однак, якщо presenter успадковується від спільного предка (наприклад, 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 автоматично передасть залежності властивостям, анотованим таким чином у презентері, щойно екземпляр буде створено.

Цей метод має ті самі недоліки, що й передача залежностей у публічну властивість. Він використовується в презентерах, оскільки не ускладнює код і вимагає мінімального набору тексту.