Методи та атрибути inject
У цій статті ми розглянемо різні способи передачі
залежностей у презентери у фреймворку Nette. Ми порівняємо бажаний
спосіб, яким є конструктор, з іншими варіантами, такими як методи та
атрибути inject
.
Навіть для презентерів передача залежностей за допомогою конструктора
є бажаним шляхом. Однак, якщо ви створюєте спільного предка, від якого
успадковуються інші презентери (наприклад, BasePresenter
), і цей
предок також має залежності, виникає проблема, яку ми називаємо constructor hell. Її
можна обійти за допомогою альтернативних шляхів, якими є методи та
атрибути (анотації) inject
.
Методи 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;
}
Перевагою цього способу передачі залежностей була дуже лаконічна форма запису. Однак з появою constructor property promotion простіше використовувати конструктор.
Навпаки, цей спосіб страждає тими ж недоліками, що й передача залежності у властивості загалом: ми не маємо контролю над змінами в змінній, і водночас змінна стає частиною публічного інтерфейсу класу, що є небажаним.