Novinky v Nette DI 3.0 beta1

David Grudl
Nette Core | 8215
+
+18
-

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/

Felix
Nette Core | 1195
+
+1
-

Pekne sepsano ;-) Bude se snadneji testovat.

CZechBoY
Člen | 3608
+
+1
-

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
+
0
-

@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

David Grudl
Nette Core | 8215
+
+3
-

@CZechBoY to dává smysl, doplnil jsem to, možné jsou oba přístupy.

josef.sabl
Člen | 153
+
+3
-

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: 👏