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 автоматически вызывает такие именованные методы сразу после создания экземпляра ведущего и передает им все необходимые зависимости. Поэтому они должны быть объявлены как public.

`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 автоматически передает зависимости сразу после создания экземпляра ведущего. Для инъекции необходимо объявить их как public.

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

```php
use Nette\DI\Attributes\Inject; // эта строка важна

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

Преимуществом этого метода передачи зависимостей была очень экономичная форма нотации. Однако, с введением [продвижения свойств конструктора |https://blog.nette.org/ru/php-8-0-polnyj-obzor-novostej#toc-constructor-property-promotion], использование конструктора кажется более простым.

С другой стороны, этот метод страдает теми же недостатками, что и передача зависимостей в свойства в целом: у нас нет контроля над изменениями переменной, и в то же время переменная становится частью публичного интерфейса класса, что нежелательно.


{{sitename: Лучшие практики}}

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

В этой статье мы рассмотрим различные способы передачи зависимостей презентаторам во фреймворке Nette. Мы сравним предпочтительный метод, которым является конструктор, с другими вариантами, такими как методы inject и атрибуты.

Для ведущих также передача зависимостей с помощью конструктора является предпочтительным способом. Однако если вы создаете общего предка, от которого наследуют другие презентаторы (например, BasePresenter), и этот предок также имеет зависимости, возникает проблема, которую мы называем адом конструктора. Ее можно обойти с помощью альтернативных методов, которые включают в себя методы инъекции и атрибуты (аннотации).

inject*() Методы

Это форма передачи зависимостей с помощью сеттеров. Имена этих сеттеров начинаются с префикса inject. Nette DI автоматически вызывает такие именованные методы сразу после создания экземпляра ведущего и передает им все необходимые зависимости. Поэтому они должны быть объявлены как public.

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 автоматически передает зависимости сразу после создания экземпляра ведущего. Для инъекции необходимо объявить их как public.

Свойства помечаются атрибутом: (ранее использовалась аннотация /** @inject */)

use Nette\DI\Attributes\Inject; // эта строка важна

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

Преимуществом этого метода передачи зависимостей была очень экономичная форма нотации. Однако, с введением продвижения свойств конструктора, использование конструктора кажется более простым.

С другой стороны, этот метод страдает теми же недостатками, что и передача зависимостей в свойства в целом: у нас нет контроля над изменениями переменной, и в то же время переменная становится частью публичного интерфейса класса, что нежелательно.