Inject-Methoden und -Attribute
Dieser Artikel widmet sich den verschiedenen Wegen, Abhängigkeiten an Presenter im Nette Framework zu
übergeben. Wir vergleichen den bevorzugten Weg, den Konstruktor, mit weiteren Möglichkeiten wie den inject-Methoden
und -Attributen.
Auch für Presenter gilt, dass die Übergabe von Abhängigkeiten über den Konstruktor der
bevorzugte Weg ist. Wenn Sie aber einen gemeinsamen Vorfahren erstellen, von dem die übrigen Presenter erben (z. B.
BasePresenter), und dieser Vorfahre ebenfalls Abhängigkeiten hat, entsteht ein Problem, das wir Constructor Hell nennen.
Umgehen lässt es sich mit alternativen Wegen, nämlich den Inject-Methoden und -Attributen (früher Annotationen).
inject*()-Methoden
Dabei handelt es sich um eine Form der Abhängigkeitsübergabe per Setter. Die Namen dieser Setter
beginnen mit dem Präfix inject. So benannte Methoden ruft Nette DI automatisch unmittelbar nach dem Erzeugen der
Presenter-Instanz auf und übergibt ihnen alle geforderten Abhängigkeiten. Sie müssen deshalb als public deklariert sein.
Die inject*()-Methoden lassen sich als eine Art Erweiterung des Konstruktors auf mehrere Methoden verstehen.
Dadurch kann der BasePresenter seine Abhängigkeiten über eine eigene Methode entgegennehmen und den Konstruktor
für seine Nachkommen frei lassen:
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;
}
}
Ein Presenter kann beliebig viele inject*()-Methoden enthalten, und jede kann beliebig viele Parameter haben.
Hervorragend eignet sich dieser Ansatz auch für Fälle, in denen ein Presenter aus Traits zusammengesetzt ist und jedes Trait eigene
Abhängigkeiten verlangt.
Inject-Attribute
Dabei handelt es sich um eine Form der Injektion in Properties. Es genügt, die Properties zu kennzeichnen, in die injiziert werden soll, und Nette DI übergibt die Abhängigkeiten automatisch unmittelbar nach dem Erzeugen der Presenter-Instanz. Damit sie eingesetzt werden können, müssen diese Properties als public deklariert sein.
Die Properties kennzeichnen wir mit einem Attribut: (früher wurde die Annotation /** @inject */ verwendet)
use Nette\DI\Attributes\Inject; // diese Zeile ist wichtig
class MyPresenter extends Nette\Application\UI\Presenter
{
#[Inject]
public Cache $cache;
}
Der Vorteil dieser Art der Abhängigkeitsübergabe war die sehr sparsame Schreibweise. Mit der Einführung von Constructor Property Promotion erscheint es jedoch einfacher, den Konstruktor zu verwenden.
Umgekehrt leidet dieser Weg an denselben Nachteilen wie die Übergabe von Abhängigkeiten in Properties allgemein: Wir haben keine Kontrolle über Änderungen der Variablen, und die Variable wird Teil der öffentlichen Schnittstelle der Klasse, was unerwünscht ist.