Nette Documentation Preview

syntax
Předávání závislostí
********************

<div class=perex>

Argumenty, nebo v terminologii DI „závislosti“, lze do tříd předávat těmito hlavními způsoby:

* předávání konstruktorem
* předávání metodou (tzv. setterem)
* nastavením proměnné
* metodou, anotací či atributem *inject*

</div>

Nyní si jednotlivé varianty ukážeme na konkrétních příkladech.


Předávání konstruktorem
=======================

Závislosti jsou předávány v okamžiku vytváření objektu jako argumenty konstruktoru:

```php
class MyClass
{
	/** @var Cache */
	private $cache;

	public function __construct(Cache $cache)
	{
		$this->cache = $cache;
	}
}

$obj = new MyClass($cache);
```

Tato forma je vhodná pro povinné závislosti, které třída nezbytně potřebuje ke své funkci, neboť bez nich nepůjde instanci vytvořit.


Předávání setterem
==================

Závislosti jsou předávány voláním metody, která je uloží do privátní proměnné. Obvyklou konvencí pojmenování těchto metod je tvar `set*()`, proto se jim říká settery, ale mohou se samozřejmě jmenovat jakkoliv jinak.

```php
class MyClass
{
	/** @var Cache */
	private $cache;

	public function setCache(Cache $cache)
	{
		$this->cache = $cache;
	}
}

$obj = new MyClass;
$obj->setCache($cache);
```

Tento způsob je vhodný pro nepovinné závislosti, které nejsou pro funkci třídy nezbytné, neboť není garantováno, že objekt závislost skutečně dostane (tj. že uživatel metodu zavolá).

Zároveň tento způsob připouští volat setter opakovaně a závislost tak měnit. Pokud to není žádoucí, přidáme do metody kontrolu.

```php
class MyClass
{
	/** @var Cache */
	private $cache;

	public function setCache(Cache $cache)
	{
		if ($this->cache) {
			throw new RuntimeException('The dependency has already been set');
		}
		$this->cache = $cache;
	}
}
```

Volání setteru definujeme v konfiguraci DI kontejneru v [klíči setup |services#Setup]. I tady se využívá automatického předávání závislostí pomocí autowiringu:

```neon
services:
	-
		create: MyClass
		setup:
			- setCache
```


Nastavením proměnné
===================

Závislosti jsou předávány zapsáním přímo do členské proměnné:

```php
class MyClass
{
	/** @var Cache */
	public $cache;
}

$obj = new MyClass;
$obj->cache = $cache;
```

Tento způsob se považuje za nevhodný, protože členská proměnná musí být deklarována jako `public`. A tudíž nemáme kontrolu nad tím, že předaná závislost bude skutečně daného typu a přicházíme o možnost reagovat na nově přiřazenou závislost vlastním kódem, například zabránit následné změně. Zároveň se proměnná stává součástí veřejného rozhraní třídy, což nemusí být žádoucí.

Nastavení proměnné definujeme v konfiraci DI kontejneru v [sekci setup |services#Setup]:

```neon
services:
	-
		create: MyClass
		setup:
			- $cache = @\Cache
```


Inject
======

Zatímco předchozí tři způsoby platí obecně ve všech objektově orientovaných jazycích, injektování metodou, anotací či atributem *inject* je specifické čistě pro presentery v Nette. Pojednává o nich [samostatná kapitola |best-practices:inject-method-attribute].


Jaký způsob zvolit?
===================

- konstruktor je vhodný pro povinné závislosti, které třída nezbytně potřebuje ke své funkci
- setter je naopak vhodný pro nepovinné závislosti, nebo závislosti, které lze mít možnost dále měnit
- veřejné proměnné vhodné nejsou

Předávání závislostí

Argumenty, nebo v terminologii DI „závislosti“, lze do tříd předávat těmito hlavními způsoby:

  • předávání konstruktorem
  • předávání metodou (tzv. setterem)
  • nastavením proměnné
  • metodou, anotací či atributem inject

Nyní si jednotlivé varianty ukážeme na konkrétních příkladech.

Předávání konstruktorem

Závislosti jsou předávány v okamžiku vytváření objektu jako argumenty konstruktoru:

class MyClass
{
	/** @var Cache */
	private $cache;

	public function __construct(Cache $cache)
	{
		$this->cache = $cache;
	}
}

$obj = new MyClass($cache);

Tato forma je vhodná pro povinné závislosti, které třída nezbytně potřebuje ke své funkci, neboť bez nich nepůjde instanci vytvořit.

Předávání setterem

Závislosti jsou předávány voláním metody, která je uloží do privátní proměnné. Obvyklou konvencí pojmenování těchto metod je tvar set*(), proto se jim říká settery, ale mohou se samozřejmě jmenovat jakkoliv jinak.

class MyClass
{
	/** @var Cache */
	private $cache;

	public function setCache(Cache $cache)
	{
		$this->cache = $cache;
	}
}

$obj = new MyClass;
$obj->setCache($cache);

Tento způsob je vhodný pro nepovinné závislosti, které nejsou pro funkci třídy nezbytné, neboť není garantováno, že objekt závislost skutečně dostane (tj. že uživatel metodu zavolá).

Zároveň tento způsob připouští volat setter opakovaně a závislost tak měnit. Pokud to není žádoucí, přidáme do metody kontrolu.

class MyClass
{
	/** @var Cache */
	private $cache;

	public function setCache(Cache $cache)
	{
		if ($this->cache) {
			throw new RuntimeException('The dependency has already been set');
		}
		$this->cache = $cache;
	}
}

Volání setteru definujeme v konfiguraci DI kontejneru v klíči setup. I tady se využívá automatického předávání závislostí pomocí autowiringu:

services:
	-
		create: MyClass
		setup:
			- setCache

Nastavením proměnné

Závislosti jsou předávány zapsáním přímo do členské proměnné:

class MyClass
{
	/** @var Cache */
	public $cache;
}

$obj = new MyClass;
$obj->cache = $cache;

Tento způsob se považuje za nevhodný, protože členská proměnná musí být deklarována jako public. A tudíž nemáme kontrolu nad tím, že předaná závislost bude skutečně daného typu a přicházíme o možnost reagovat na nově přiřazenou závislost vlastním kódem, například zabránit následné změně. Zároveň se proměnná stává součástí veřejného rozhraní třídy, což nemusí být žádoucí.

Nastavení proměnné definujeme v konfiraci DI kontejneru v sekci setup:

services:
	-
		create: MyClass
		setup:
			- $cache = @\Cache

Inject

Zatímco předchozí tři způsoby platí obecně ve všech objektově orientovaných jazycích, injektování metodou, anotací či atributem inject je specifické čistě pro presentery v Nette. Pojednává o nich samostatná kapitola.

Jaký způsob zvolit?

  • konstruktor je vhodný pro povinné závislosti, které třída nezbytně potřebuje ke své funkci
  • setter je naopak vhodný pro nepovinné závislosti, nebo závislosti, které lze mít možnost dále měnit
  • veřejné proměnné vhodné nejsou