Generované továrny

Nette DI umí automaticky generovat kód továren na základě rozhraní, což vám ušetří psaní kódu.

Továrna je třída, která vyrábí a konfiguruje objekty. Předává jim tedy i jejich závislosti. Jak taková továrna vypadá jsme si ukázali v úvodní kapitole:

class ArticleFactory
{
	private Nette\Database\Connection $db;

	public function __construct(Nette\Database\Connection $db)
	{
		$this->db = $db;
	}

	/** @return Article */
	public function create()
	{
		return new Article($this->db);
	}
}

Nette DI umí kód továren automaticky generovat. Vše, co musíte udělat, je vytvořit rozhraní a Nette DI vygeneruje implementaci. Rozhraní musí mít přesně jednu metodu s názvem create a deklarovat návratový typ:

interface ArticleFactory
{
	/** @return Article */
	function create();
}

Tedy továrna ArticleFactory má metodu create, která vytváří objekty Article. Třída Article může vypadat třeba následovně:

class Article
{
	private $db;

	public function __construct(Nette\Database\Connection $db)
	{
		$this->db = $db;
	}
}

Továrnu přidáme do konfiguračního souboru:

services:
	- ArticleFactory

Nette DI vygeneruje odpovídající implementaci továrny.

V kódu, který továrnu používá, si tak vyžádáme objekt podle rozhraní a Nette DI použije vygenerovanou implementaci:

class UserController
{
	private $articleFactory;

	public function __construct(ArticleFactory $articleFactory)
	{
		$this->articleFactory = $articleFactory;
	}

	public function foo()
	{
		// necháme továrnu vytvořit objekt
		$article = $this->articleFactory->create();
	}
}

Parametrizovaná továrna

Tovární metoda create může přijímat parametry, které poté předá do konstrukturu. Doplňme například třídu Article o ID autora článku:

class Article
{
	private $db;
	private $authorId;

	public function __construct(Nette\Database\Connection $db, $authorId)
	{
		$this->db = $db;
		$this->authorId = $authorId;
	}
}

Parametr přidáme také do továrny:

interface ArticleFactory
{
	/** @return Article */
	function create(int $authorId);
}

Díky tomu, že se parametr v konstruktoru i parametr v továrně jmenují stejně, Nette DI je zcela automaticky předá.

Pokročilá definice

Definici lze zapsat i ve víceřádkové podobě za použití klíče implement:

services:
	articleFactory:
		implement: ArticleFactory

Při zápisu tímto delším způsobem je možné uvést další argumenty pro konstruktor v klíči arguments a doplňující konfiguraci pomocí setup, stejně, jako u běžných služeb.

Příklad: pokud by metoda create() nepřijímala parametr $authorId, mohli bychom uvést pevnou hodnotu v konfiguraci, která by se předávala do konstruktoru Article:

services:
	articleFactory:
		implement: ArticleFactory
		arguments:
			authorId: 123

Accessor

Nette umí krom továren generovat i tzv. accessory. Jde o objekty s metodou get(), která vrací určitou službu z DI kontejneru. Opakované volání get() vrací stále tutéž instanci.

Accessor poskytují závislostem lazy-loading. Mějme třídu, která zapisuje chyby do speciální databáze. Když by si tato třída nechávala připojení k databázi předávat jako závislost konstruktorem, muselo by se připojení vždycky vytvořit, ačkoliv v praxi se chyba objeví jen výjimečně a tedy povětšinou by zůstalo spojení nevyužité. Místo toho si tak třída předá accessor a teprve když se zavolá jeho get(), dojde k vytvoření objektu databáze:

Jak accessor vytvořit? Stačí napsat rozhraní a Nette DI vygeneruje implementaci. Rozhraní musí mít přesně jednu metodu s názvem get a deklarovat návratový typ:

interface PDOAccessor
{
	function get(): PDO;
}

Accessor přidáme do konfiguračního souboru, kde je také definice služby, kterou bude vracet:

services:
	- PDOAccessor
	- PDO(%dsn%, %user%, %password%)

Protože accessor vrací službu typu PDO a v konfiguraci je jediná taková služba, bude vracet právě ji. Pokud by služeb daného typu bylo víc, určíme vracenou službu pomocí názvu, např. - PDOAccessor(@db1).

verze: 3.x 2.x