πΏ
composer require dakujem/nette-wires
Wire Genie umoznuje redukovat "boilerplate" kod suvisiaci s drotovanim sluzieb cez prezentery (napriklad vytvaranie komponent a niektorych jednorazovych sluzieb typu builder alebo factory).
Ale bacha! π€
V zavislosti od konkretneho pouzitia moze dojst k poruseniu IoC principov a degradacii dependency injection principov na service locator. Pouzivajte na vlastnu zdpovednost, ak viete, co robite.
Na druhej strane, ak vytiahujete sluzby z kontajneru, mozete uz radsej pouzit Wire Genie.
πΏ
composer require dakujem/nette-wires
Tento metapackage instaluje Wire Genie a navod nizsie odporuca instalaciu Contributte/PSR-11-kontajner, ale mozete pouzit lubovolny iny PSR-11 wrapper Nette DI kontajneru.
Pokial si nainstalujete contributte/psr11-container-interface
,
mozete vo svojom bazovom prezenteri pouzit
WireGenieTrait
,
ktory prida do prezenteru metodu wire
.
composer require contributte/psr11-container-interface
namespace App\Presenters;
use Dakujem\WireGenieTrait;
use Nette;
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
use WireGenieTrait;
}
π‘ Nepouzivajte traity, pokial nerozumiete, co s nimi nie je v poriadku.
Implementacia wire
metody je inak vo vasich rukach.
Namiesto nej mozete tiez priamo volat $wireGenie->provide( ... )->invoke( ... )
.
Metodu wire
je mozne pouzit napriklad v createComponent*
metodach:
protected function createComponentFoobarForm()
{
$factory = function (InputFactory $inputs, TextRepository $textRepo) {
$form = new Form();
$form->addComponent(
$inputs->create('stuff', $textRepo->getAllUnread()),
'unread_stuff'
);
// ...
return $form;
};
// explicitne vyziadanie zavislosti
return $this->wire(InputFactory::class, 'model.repository.text')->invoke($factory);
// alebo automaticke nadrotovanie zavislosti (autowiring)
return $this->wire()->invoke($factory);
}
Lepsie je zabalit kod do tovarne alebo populatoru (moznost testovat):
protected function createComponentFoobarForm()
{
return $this->wire(InputFactory::class, 'model.repository.text')
->invoke([new FoobarFormFactory, 'create']);
}
Lokalne zavislosti z prezenteru je mozne pribalit cez anonymne funkcie:
protected function createComponentFoobarForm()
{
return $this->wire(InputFactory::class, 'model.repository.text')
->invoke(function (...$deps) {
return (new FoobarFormFactory)->create(
$this->localDependency,
$this->getParameter('id'),
...$deps
);
});
}
Tento postup umoznuje vyhnut sa injektovaniu mnozstva zavislosti do prezenterov, pokial nie su vzdy pouzivane (prezetner moze mat viacero akcii, pouzije sa len jedna; komponenty detto).
Taketo pouzitie Wire Genie riesi okrajovy pripad, kedy vznika boilerplate.
Pred pouzitim skuste pouvazovat, ci sa vas pripad neda vyriesit cistejsie.
Nette 3 podporuje injektovanie skupin sluzieb, SearchExtension
umoznuje hromadne registrovat sluzby do kontajneru, atd.
Porovnajte vyhody a nevyhody:
- β zachovanie IoC je otazne (zalezi na uhle pohladu)
- β vyhodou je mala pracnost riesenia
- β prehladne prepojenie zavislosti, jednoduche na pochopenie
- β autowiring, vid detaily v balicku Wire Genie
- β moznost konfiguracie drotovania zavislosti existuje
- β testovatelnost je jednoduchsia ako v priapde tovarni vygenerovanych DI
- β prezenter neriesi, odkial zavislosti tecu, ale deklaruje, ake sluzby sa maju nadrotovat
- β lazy loading v momente realneho pouzitia
- β βmaskovanyβ service lokator (β)
- β kontajner pri kompilacii nezisti problemy s chybajucimi alebo konfliktnymi sluzbami
Alternativne mozete skusit iny kompromis, napr. Kdyby/Autowired.
Osobne odporucam tieto techniky pouzivat len vo faze prototypovania.
Allows to fetch multiple dependencies from a DI container
and provide them as arguments to a callable.
Metapackage.
Disclaimer π€
Depending on actual use, this might be breaking IoC and degrade your dependency injection container to a service locator, so use it with caution.
But then again, if you can
get
a service from your container, you can use wire genie.
πΏ
composer require dakujem/nette-wires
Then either install Contributte/PSR-11-kontajner or any other PSR-11 wrapper for Nette DI container.
If you install contributte/psr11-container-interface
,
you can use
WireGenieTrait
,
in your presenter(s), that will add wire
method.
composer require contributte/psr11-container-interface
namespace App\Presenters;
use Dakujem\WireGenieTrait;
use Nette;
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
use WireGenieTrait;
}
π‘ Do not use traits unless you understand what's wrong with them.
Otherwise, implementation of wire
method is in your hands.
You can of course call $wireGenie->provide( ... )->invoke( ... )
directly as well.
Then you can wire dependencies without first labourously injecting them to your presenters, creating factories and accessors in the meantime.
protected function createComponentFoobarForm()
{
$factory = function (InputFactory $inputs, TextRepository $textRepo) {
$form = new Form();
$form->addComponent(
$inputs->create('stuff', $textRepo->getAllUnread()),
'unread_stuff'
);
// ...
return $form;
};
// with explicit dependencies
return $this->wire(InputFactory::class, 'model.repository.text')->invoke($factory);
// with automatic dependency resolution (autowiring)
return $this->wire()->invoke($factory);
}
Local dependencies can naturally be passed to the closures:
protected function createComponentFoobarForm()
{
return $this->wire(InputFactory::class, 'model.repository.text')
->invoke(function (...$deps) {
return (new FoobarFormFactory)->create(
$this->localDependency,
$this->getParameter('id'),
...$deps
);
});
}
Please understand that this approach has its advantages and disadvantages.
It might actually degrade your aplication if misused.
First try to think if your case can not be solved in a cleaner way.\
I would recommend only using this and similar approaches during prototyping phase.