Pokud se budeme řídit pravidlem „>>Zapomeňte, že existuje nějaký $this->context,<<“ budeme si muset do presenterů předávat závislosti jiným způsobem.
Jednou z novinek v Nette 2.0.5 je autowire pomocí inject metod v presenteru. Ve své podstatě se jedná o setter injection s jedním rozdílem oproti běžnému setteru -- bežný setter je možné volat opakovaně. Inject metody se naopak smí volat pouze jednou (v opačném případě by mohlo dojít k nečekanému chování) a metoda sama by v případě opakovaného volání měla vyhazovat výjimku.
Ukázka
abstract class BasePresenter extends \Nette\Application\UI\Presenter
{
/** @var Settings */
protected $settings;
/**
* @param Settings
*/
public function injectSettings(Settings $settings)
{
if ($this->settings) {
throw new Nette\InvalidStateException('Settings has already been set');
}
$this->settings = $settings;
}
protected function beforeRender()
{
$this->template->appName = $this->settings->get('appName');
}
}
class ArticlesPresenter extends BasePresenter
{
/** @var Articles */
protected $articles;
/**
* @param Articles
*/
public function injectArticles(Articles $articles)
{
if ($this->articles) {
throw new Nette\InvalidStateException('Articles has already been set');
}
$this->articles = $articles;
}
public function renderDetail($id = 0)
{
// pochopitelně zde by nejprve měla být kontrola, zda vůbec článek existuje atd.
$this->template->article = $this->articles->find($id);
}
}
Nette nám automaticky do Articles presenteru předá námi očekávané služby, tj. službu, jež je typu Articles (skrze volání metody injectArticles) a službu typu Settings (již potřebuje BasePresenter).
Problémy
Autowire je automatizace a žádná automatizace není zcela dokonalá. I autowiring pomocí inject metod má své mouchy.
Více instancí nebo implementací požadovaného typu
Uvažujme, že máme takovouto inject metodu:
public function injectFoo(IFoo $foo) { ... }
Zároveň předpokládejme, že v DI containeru máme více služeb implementujících námi žádané rozhraní IFoo. V tento moment nastává situace, kdy autowiring není technicky možný -- Nette není schopno rozpoznat, kterou z možných instancí požadujeme a vyhodí výjimku.
Podívejte se na potenciální budoucí řešení tohoto problému na fóru.
Parametry a továrničky
Skrze inject metody lze předávat pouze služby (objekty). Nelze takto automaticky předávat továrničky, ani parametry.
Budoucnost
V aktuální vývojové verzi Nette (2.1-dev) jsou inject metody automaticky volány i na všech službách a továrničkách v DI containeru. Tuto funkcionalitu je možné u jednotlivých služeb nebo továrniček vypnout:
services:
foo:
class: Foo
inject: no # vypne volání inject
Pokud se budeme řídit pravidlem „>>Zapomeňte, že existuje nějaký
$this->context
,<<“ budeme si muset do presenterů předávat závislosti jiným způsobem.Jednou z novinek v Nette 2.0.5 je autowire pomocí inject metod v presenteru. Ve své podstatě se jedná o setter injection s jedním rozdílem oproti běžnému setteru -- bežný setter je možné volat opakovaně. Inject metody se naopak smí volat pouze jednou (v opačném případě by mohlo dojít k nečekanému chování) a metoda sama by v případě opakovaného volání měla vyhazovat výjimku.
Ukázka
Nette nám automaticky do Articles presenteru předá námi očekávané služby, tj. službu, jež je typu
Articles
(skrze volání metody injectArticles) a službu typuSettings
(již potřebuje BasePresenter).Problémy
Autowire je automatizace a žádná automatizace není zcela dokonalá. I autowiring pomocí inject metod má své mouchy.
Více instancí nebo implementací požadovaného typu
Uvažujme, že máme takovouto inject metodu:
Zároveň předpokládejme, že v DI containeru máme více služeb implementujících námi žádané rozhraní
IFoo
. V tento moment nastává situace, kdy autowiring není technicky možný -- Nette není schopno rozpoznat, kterou z možných instancí požadujeme a vyhodí výjimku.Podívejte se na potenciální budoucí řešení tohoto problému na fóru.
Parametry a továrničky
Skrze inject metody lze předávat pouze služby (objekty). Nelze takto automaticky předávat továrničky, ani parametry.
Budoucnost
V aktuální vývojové verzi Nette (2.1-dev) jsou inject metody automaticky volány i na všech službách a továrničkách v DI containeru. Tuto funkcionalitu je možné u jednotlivých služeb nebo továrniček vypnout: