Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/dakujem/nette-wires

Metapackage for Nette framework.
https://github.com/dakujem/nette-wires

nette nette-di

Last synced: about 1 month ago
JSON representation

Metapackage for Nette framework.

Awesome Lists containing this project

README

        

# Nette Wires

> πŸ’Ώ `composer require dakujem/nette-wires`

- [EN version](#en-)

## SK ![sk_SK](https://www.countryflags.io/sk/flat/32.png) / CS ![cs_CZ](https://www.countryflags.io/cz/flat/24.png)

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](https://github.com/dakujem/wire-genie)
a navod nizsie odporuca instalaciu
[Contributte/PSR-11-kontajner](https://github.com/contributte/psr11-container-interface),
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`](src/WireGenieTrait.php),
ktory prida do prezenteru metodu `wire`.
> `composer require contributte/psr11-container-interface`

```php
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:
```php
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):
```php
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:
```php
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](https://github.com/dakujem/wire-genie#automatic-dependency-resolution)
- βž• 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](https://github.com/Kdyby/Autowired).

Osobne odporucam tieto techniky pouzivat len vo faze prototypovania.

## EN ![en_GB](https://www.countryflags.io/gb/flat/32.png)

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](https://github.com/contributte/psr11-container-interface)
or any other PSR-11 wrapper for Nette DI container.

If you install `contributte/psr11-container-interface`,
you can use
[`WireGenieTrait`](src/WireGenieTrait.php),
in your presenter(s), that will add `wire` method.
> `composer require contributte/psr11-container-interface`

```php
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.

```php
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:
```php
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.