Klávesové zkratky na tomto webu - základní Na obsah stránky

DI – best practise

Souhrn z přednášky Filipa Procházky, kde z praktického hlediska popisoval Depency Injection v Nette 2.1. Video z přednáškou na konci této stránky.

Typy injekce

Modely

Presentery

Presenter v DI kontejneru

Nově lze presentery registrovat v DIC jako služby, PresenterFactory se nejprve pokusí získat presenter z DI, až poté vytváří vlastní instanci.

services:
    productListPresenter:
        class: ShopModule\ProductsPresenter()
        setup:
            - $tempPath(%tempPath%)

    #nebo
    - ShopModule\ProductsPresenter()

Komponenty

Jak dostat komponentu do presenteru?

Problém, který musíme vyřešit je to, jak dostat komponentu do presenteru:

protected function createComponentForm()
{
    return new OrderForm($entityManager???);
}

Potřebuji do formuláře dostat určitou závislost – jak to udělám?

Tip: komponenty v Nette popisoval na jedné Posobotě Jan Tvrdík ve své přednášce Jak na komponenty v Nette

Komponenta má být znovupoužitelná část, kterou můžu použít vícekrát, nedává proto smysl registrovat komponenty do DIC jako služby. Nejlepším možným řešením je použít továrničky. Vytvořme si továrničku OrderFormFactory:

class OrderFormFactory {
    private $em;

    function __construct(EntityManager $em) { ... }

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

Tuto třídu si zaregistrujeme do DIC jako službu a presenteru si pak vyžádám OrderFormFactory, kterou použiju v presenteru v továrničce komponenty (metodě createComponentForm). Ještě jednodušším řešením je využít generované továrničky.

Generované továrničky

Napíšu si interface:

interface IOrderFormFactory {
    /** @return OrderForm */
    function create();
}

Tím se zbavíme povinnosti psát ručně kód továrniček jako byla např. OrderFormFactory, DIC se postará o vytvoření odpovídající továrničky automaticky.

Poznámka: metoda v interface se musí jmenovat create.

V konfiguraci poté už jen stačí říct Nette, že chci službu, která implementuje toto rozhraní.

services:
    orderFormFactory:
        implement: IOrderFormFactory

    #nebo
    - {implement: IOrderFormFactory}

Nette nám vygeneruje továrničku, která vytvoří instance třídy OrderForm. OrderForm může bezproblémů používat autowire, lze mu předávat parametry apod. Generovaná továrnička se postará, aby OrderForm dostal vše co potřebuje.

Poté stačí už jen vyžádat si v presenteru službu implementující IOrderFormFactory a použít jí pro vytvoření komponenty:

/** @var IOrderFormFactory @inject */
public $orderFormFactory;

protected function createComponentOrderForm()
{
    $form = $this->orderFormFactory->create();
    $form->onSuccess[] = ...;
    return $form;
}

Tip: pokud chcete komponentu použít na více místech, je dobré nedávat výsledná přesměrování přímo do formuláře (komponenty), ale přidat je k formuláři až v dané továrničce (metodě createComponent*).

Poznámka: ne vždy lze generované továrničky použít, někdy je lepší napsat továrničku ručně.

Rozšíření

V Nette existuje koncept rozšíření.

class OrmExtension extends CompilerExtension {
    # vytvori sluzby (zaregistruje je v DIC)
    public function loadConfiguration() { }

    # upravuje své a jiné služby
    public function beforeCompile() { }

    # hackuje vytvořený DI container
    public function afterCompile() { }
}

Jak vypadá dobré rozšíření:

Video

Zdroje

Další užitečné informace:

Poslední změna: 16.05.2014

Nalezli jste nějakou chybu, či nepřesnost? Dejte mi o ní vědět!