Méthodes et attributs inject
Cet article se concentre sur les différentes façons de passer des dépendances aux presenters dans le framework
Nette. Nous comparerons la méthode préférée, l'injection par le constructeur, avec des alternatives comme les méthodes et les
attributs inject.
Pour les presenters, comme pour les autres classes, passer les dépendances par le constructeur est l'approche
préférée. Cependant, si vous créez un ancêtre commun dont héritent les autres presenters (par exemple
BasePresenter) et que cet ancêtre a lui aussi besoin de dépendances, un problème appelé constructor hell peut apparaître. On peut le
contourner par des méthodes alternatives, à savoir les méthodes et les attributs inject (autrefois des annotations).
Méthodes inject*()
C'est une forme de passage des dépendances par setters. Les noms de ces setters doivent
commencer par le préfixe inject. Nette DI appelle automatiquement les méthodes ainsi nommées juste après la
création de l'instance du presenter, en leur passant toutes les dépendances requises. Elles doivent donc être déclarées
publiques.
Les méthodes inject*() peuvent être vues comme des extensions du constructeur, réparties en plusieurs
méthodes. Cela permet à BasePresenter de recevoir ses dépendances par une méthode distincte, en laissant le
constructeur libre pour ses descendants :
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;
}
}
Un presenter peut avoir autant de méthodes inject*() que nécessaire, et chacune peut accepter autant de
paramètres que nécessaire. Cette approche convient aussi très bien aux cas où un presenter est composé de traits et où chaque trait a besoin de ses propres dépendances.
Attributs Inject
C'est une forme d'injection dans les propriétés. Il suffit de marquer les propriétés à injecter et Nette DI passera automatiquement les dépendances juste après la création de l'instance du presenter. Pour permettre l'injection, ces propriétés doivent être déclarées publiques.
Les propriétés se marquent par un attribut : (auparavant, on utilisait l'annotation /** @inject */)
use Nette\DI\Attributes\Inject; // cette ligne est importante
class MyPresenter extends Nette\Application\UI\Presenter
{
#[Inject]
public Cache $cache;
}
L'avantage de cette façon de passer les dépendances était sa forme d'écriture très concise. Cependant, avec l'arrivée de la promotion des propriétés du constructeur, utiliser le constructeur paraît souvent plus simple.
En revanche, cette méthode souffre des mêmes défauts que l'injection dans les propriétés en général : nous perdons le contrôle sur les changements de la variable, et celle-ci devient partie de l'interface publique de la classe, ce qui est généralement indésirable.