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

У цій статті ми розглянемо різні способи передачі залежностей доповідачам у фреймворку 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;
}

Перевагою такого способу передачі залежностей була дуже економна форма запису. Однак, із запровадженням популяризації властивостей конструктора, використання конструктора видається простішим.

З іншого боку, цей спосіб страждає тими ж недоліками, що і передача залежностей у властивості взагалі: ми не маємо контролю над змінами змінної, і в той же час змінна стає частиною публічного інтерфейсу класу, що є небажаним.