Metody a atributy inject

V tomto článku se zaměříme na různé způsoby předávání závislostí do presenterů v Nette frameworku. Porovnáme preferovaný způsob, kterým je konstruktor, s dalšími možnostmi, jako jsou metody a atributy inject.

I pro presentery platí, že předání závislostí pomocí konstruktoru je preferovaná cesta. Pokud ale vytváříte společného předka, od kterého dědí ostatní presentery (např. BasePresenter), a tento předek má také závislosti, nastane problém, kterému říkáme constructor hell. Ten lze obejít pomocí alternativních cest, které představují metody a atributy (anotace) inject.

Metody inject*()

Jde o formu předávání závislosti setterem. Název těchto setterů začíná předponou inject. Nette DI takto pojmenované metody automaticky zavolá hned po vytvoření instance presenteru a předá jim všechny požadované závislosti. Musí být tudíž deklarované jako public.

Metody inject*() lze považovat za jakési rozšíření konstruktoru do více metod. Díky tomu může BasePresenter převzít závislosti přes jinou metodu a ponechat konstruktor volný pro své potomky:

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;
	}
}

Metod inject*() může presenter obsahovat libovolný počet a každá může mít libovolný počet parametrů. Skvěle se hodí také v případech, kdy je presenter složen z trait a každá z nich si žádá vlastní závislost.

Atributy Inject

Jde o formu injektování do property. Stačí označit, do kterých proměnných se má injektovat, a Nette DI automaticky předá závislosti hned po vytvoření instance presenteru. Aby je mohl vložit, je nutné je deklarovat jako public.

Properites označíme atributem: (dříve se používala anotace /** @inject */)

use Nette\DI\Attributes\Inject;  // tento řádek je důležitý

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

Výhodou tohoto způsobu předávání závislostí byla velice úsporná podoba zápisu. Nicméně s příchodem constructor property promotion se jeví snazší použít konstruktor.

Naopak tento způsob trpí stejnými nedostatky, jako předávání závislosti do properties obecně: nemáme kontrolu nad změnami v proměnné a zároveň se proměnná stává součástí veřejného rozhraní třídy, což je nežádnoucí.