Metode și atribute inject

În acest articol ne vom concentra pe diferite modalități de a transmite dependențe către presenteri în framework-ul Nette. Vom compara metoda preferată, care este constructorul, cu alte opțiuni, cum ar fi metodele și atributele inject.

Și pentru presenteri este valabil că transmiterea dependențelor prin constructor este calea preferată. Dacă însă creați un strămoș comun din care moștenesc alți presenteri (de ex. BasePresenter), și acest strămoș are de asemenea dependențe, apare o problemă pe care o numim constructor hell. Aceasta poate fi ocolită folosind căi alternative, reprezentate de metode și atribute (anterior adnotări) inject.

Metode inject*()

Este o formă de transmitere a dependenței prin setter. Numele acestor setteri începe cu prefixul inject. Nette DI apelează automat metodele numite astfel imediat după crearea instanței presenterului și le transmite toate dependențele necesare. Prin urmare, trebuie declarate ca public.

Metodele inject*() pot fi considerate un fel de extensie a constructorului în mai multe metode. Datorită acestui fapt, BasePresenter poate prelua dependențe printr-o altă metodă și lăsa constructorul liber pentru descendenții săi:

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 poate conține un număr arbitrar de metode inject*() și fiecare poate avea un număr arbitrar de parametri. Se potrivesc excelent și în cazurile în care presenterul este compus din trait-uri și fiecare dintre ele necesită propria dependență.

Atribute Inject

Este o formă de injectare în proprietate. Este suficient să marcați în ce variabile trebuie injectat, iar Nette DI transmite automat dependențele imediat după crearea instanței presenterului. Pentru a le putea insera, este necesar să le declarați ca public.

Marcăm proprietățile cu atributul: (anterior se folosea adnotarea /** @inject */)

use Nette\DI\Attributes\Inject;  // această linie este importantă

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

Avantajul acestei metode de transmitere a dependențelor a fost forma foarte concisă a scrierii. Cu toate acestea, odată cu apariția constructor property promotion, pare mai ușor să folosești constructorul.

Pe de altă parte, această metodă suferă de aceleași neajunsuri ca și transmiterea dependențelor către proprietăți în general: nu avem control asupra modificărilor din variabilă și, în același timp, variabila devine parte a interfeței publice a clasei, ceea ce este nedorit.