Методы и атрибуты инъекции
В этой статье мы рассмотрим различные способы передачи
зависимостей презентаторам во фреймворке 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;
}
Преимуществом этого метода передачи зависимостей была очень экономичная форма нотации. Однако, с введением продвижения свойств конструктора, использование конструктора кажется более простым.
С другой стороны, этот метод страдает теми же недостатками, что и передача зависимостей в свойства в целом: у нас нет контроля над изменениями переменной, и в то же время переменная становится частью публичного интерфейса класса, что нежелательно.