Nette Documentation Preview

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

.[perex]
У цій статті ми розглянемо різні способи передачі залежностей доповідачам у фреймворку Nette. Ми порівняємо основний метод, яким є конструктор, з іншими варіантами, такими як `inject` методи та атрибути.

Для доповідачів передача залежностей за допомогою [конструктора |dependency-injection:passing-dependencies#Constructor Injection] є найкращим способом.
Однак, якщо ви створюєте спільного предка, від якого успадковують інші доповідачі (наприклад, BasePresenter), і цей предок також має залежності, виникає проблема, яку ми називаємо пеклом [конструктора |dependency-injection:passing-dependencies#Constructor hell].
Це можна обійти за допомогою альтернативних методів, до яких відносяться методи ін'єкції та атрибути (анотації).


`inject*()` Методи .[#toc-inject-methods]
=========================================

Це форма передачі залежності за допомогою [сетерів |dependency-injection:passing-dependencies#Setter Injection]. Назви цих сеттерів починаються з префікса inject.
Nette DI автоматично викликає такі іменовані методи одразу після створення екземпляра презентатора і передає їм усі необхідні залежності. Тому вони повинні бути оголошені як загальнодоступні.

`inject*()` методи можна розглядати як своєрідне розширення конструктора на декілька методів. Завдяки цьому `BasePresenter` може отримувати залежності через інший метод і залишати конструктор вільним для своїх нащадків:

```php
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*()`, і кожен з них може мати будь-яку кількість параметрів. Це також чудово підходить для випадків, коли презентер [складається з ознак |presenter-traits], і для кожної з них потрібна своя залежність.


`Inject` Атрибути .[#toc-inject-attributes]
===========================================

Це форма ін' [єкції у властивості |dependency-injection:passing-dependencies#Property Injection]. Достатньо вказати, які властивості потрібно вставити, і Nette DI автоматично передасть залежності одразу після створення екземпляра доповідача. Щоб вставити їх, необхідно оголосити їх загальнодоступними.

Властивості позначаються атрибутом: (раніше використовувалася анотація `/** @inject */`)

```php
use Nette\DI\Attributes\Inject; // цей рядок важливий

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

Перевагою такого способу передачі залежностей була дуже економна форма запису. Однак, із запровадженням популяризації [властивостей конструк |https://blog.nette.org/uk/php-8-0-povnij-oglyad-novin#toc-constructor-property-promotion]тора, використання конструктора видається простішим.

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


{{sitename: Найкращі практики}}

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

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

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

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