Nette Documentation Preview

syntax
Metody a atributy inject
************************

.[perex]
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 |dependency-injection:passing-dependencies#Předávání konstruktorem] 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 |dependency-injection:passing-dependencies#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 |dependency-injection:passing-dependencies#Předávání 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:

```php
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 |presenter-traits] a každá z nich si žádá vlastní závislost.


Atributy `Inject`
=================

Jde o formu [injektování do property |dependency-injection:passing-dependencies#Nastavením proměnné]. 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 */`)

```php
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 |https://blog.nette.org/cs/php-8-0-kompletni-prehled-novinek#toc-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 properites 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í.


{{sitename: Best Practices}}

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 properites 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í.