Novinky v Nette DI 3.0 beta1
- David Grudl
- Nette Core | 8227
Před chvílí vyšla první betaverze Nette DI 3.0. Prosím, otestujte ji.
Jaké jsou novinky?
Proměnné lze používat v klíčích
parameters:
username: user
password: 1234
serviceName: auth
services:
%serviceName%: Nette\Security\SimpleAuthenticator([%username%: %password%])
Autowiring kolekce služeb
Automaticky předá do konstruktoru pole všech objektů AuthSubscriber z kontejneru.
namespace App\Model;
class FacebookAuthenticator
{
/**
* @param AuthSubscriber[] $subscribers
*/
public function __construct(array $subscribers) { ... }
}
Kolekce služeb v konfiguraci
Obdoba výše zmíněného autowiringu kolekce služeb, jen definovaná
ručně v konfiguraci pomocí typed()
:
services:
- App\Model\CacheCleanerAuthSubscriber # implementuje App\Model\AuthSubscriber
- App\Model\LoggerAuthSubscriber # implementuje App\Model\AuthSubscriber
# předá pole obou subscriberů
- App\Model\FacebookAuthenticator( typed(App\Model\AuthSubscriber) )
Nebo pomocí tagů a tagged()
:
services:
-
create: App\Model\CacheCleanerAuthSubscriber
tags:
listener: foo
-
create: App\Model\LoggerAuthSubscriber
tags:
listener: bar
# předá pole obou objektů s tagem 'listener'
- App\Model\FacebookAuthenticator( tagged(listener) )
Lze vytvořit kolekci i z více tagů nebo tříd, např.
tagged(listener, anothertag)
.
Generované multi továrny a accessory:
Nette vygeneruje implementaci pro multi-accessor nebo multi-továrnu, která
umí zpřístupnit nebo vytvořit víc různých objektů podle parametru
$name
:
interface MultiAccessor
{
function get($name): Listener
}
services:
- App\Model\CacheCleanerAuthSubscriber
- App\Model\LoggerAuthSubscriber
third: App\Model\DummyAuthSubscriber
- MultiAccessor(
sub1: @App\Mode\CacheCleanerAuthSubscriber
sub2: @App\Model\LoggerAuthSubscriber
sub3: @third
)
Použití:
$sub1 = $multiAccessor->get('sub1'); // vrací objekt App\Mode\CacheCleanerAuthSubscriber
$sub2 = $multiAccessor->get('sub2'); // vrací objekt App\Model\LoggerAuthSubscriber
Stejně tak lze vytvořit multitovárnu:
interface MultiFactory
{
function create($name): Listener
}
$sub1 = $multiFactory->create('sub1'); // vyrobí nový App\Mode\CacheCleanerAuthSubscriber
Neexistující služba:
$multiFactory->create('UNDEFINED'); // throws Nette\DI\MissingServiceException
// nebo lze vytvořit nullable továrnu:
interface MultiFactory
{
function create($name): ?Listener // nullable typ
}
$multiFactory->create('UNDEFINED'); // vrací null
Multitovárnu lze definovat také pomocí tagů:
services:
-
create: App\Model\CacheCleanerAuthSubscriber
tags:
listener: sub1
-
create: App\Model\LoggerAuthSubscriber
tags:
listener: sub2
- MultiAccessor(tagged: listener)
Objekty jsou pak dostupné pod názvy, které odpovídají hodnotám tagů, tj. sub1 a sub2.
Co se ještě objeví?
Možnost nechat automaticky přidávat jako služby určité třídy v určitých adresářích. Tedy podobně, jako to už funguje několik let u presenterů
Díky za inspiraci @Felix a https://f3l1x.io/…y-injection/
- CZechBoY
- Člen | 3608
Super.
Nešlo by místo
$multiFactory->create('sub1');
$multiFactory->create('sub2');
použít jen metodu bez parametru?
$multiFactory->createSub1();
$multiFactory->createSub2();
Interface by potom vypadal takto
interface MultiFactory
{
function createSub1(): Sub1;
function createSub2(): Sub2;
}
- David Matějka
- Moderator | 6445
@CZechBoY to, co popisujes, je zcela jiny use case.
to, co David implementoval, resi situaci, kdy tovarna vraci jeden typ objektu (pripadne subtyp) a je veci konfigurace (nikoliv tedy kontraktu v rozhrani), jake definice tovarny a pod jakymi nazvy budou existovat
- josef.sabl
- Člen | 153
Zrovna dnes jsme řešili jeden problém, kdy jsme si říkali, že by se nám hodil „Autowiring kolekce služeb“ a druhý problém z dneška nám elegantně řeší „Možnost nechat automaticky přidávat jako služby určité třídy v určitých adresářích“. Takže: 👏