dakujem / nette-wires
Wire in Nette with genie powers.
Requires
- php: >=7.2
- dakujem/wire-genie: ^1.1
Requires (Dev)
- contributte/psr11-container-interface: ^0.4.1 || ^0.3
This package is auto-updated.
Last update: 2024-10-22 19:41:52 UTC
README
πΏ
composer require dakujem/nette-wires
SK / CS
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.
Instalacia
πΏ
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( ... )
.
Pouzitie
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.
EN
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.
Installation
πΏ
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.