Nette 3: dependency injection 10/10/2018

Jak by mohlo vypadat dependency injection v Nette 3.0.

Již jednou jsem psal o dependency injection v Nette, konkrétně Nette - jak zapisovat služby (extension / neon). Do dnes asi můj nejlepší článek.

K tomuto článku mě donutily změny v nette/di repozitáři. Myslím, že David zase vymyslel elegantní features. A také tyto tweety.


Nette 2.4

Pojďme si zopakovat některé základní definice zapisování služeb v NEONu.

Anonymní služba

services:
	- App\Model\FacebookAuthenticator
$container->getByType(App\Model\FacebookAuthenticator::class);

Pojmenovaná služba

services:
	facebookAuth: App\Model\FacebookAuthenticator
$container->getByType(App\Model\FacebookAuthenticator::class);
$container->getService('facebookAuth');

Předávání závislostí

services:
	- App\Model\FacebookAuthenticator(
		App\Model\MonologLogger(@monolog),
		App\Model\CacheAdapter(
			FileCache(%tempDir%/auth)
		)
	)
$container->getByType(App\Model\FacebookAuthenticator::class);

Volání metod na službě

services:
	facebookAuth:
		class: App\Model\FacebookAuthenticator
		setup:
			# autowiring vybere správnou službu
			- setLogger
			# sám definuji konkrétní pojmenovanou službu
			- setLogger(@monologLogger)
			# sám definuji konkrétní anonymní službu
			- setLogger(@App\Model\MonologLogger)
$container->getByType(App\Model\FacebookAuthenticator::class);
$container->getService('facebookAuth');

Více služeb stejného typu

services:
	facebookAuth:
		class: App\Model\FacebookAuthenticator
		autowired: false
	twitterAuth:
		class: App\Model\TwitterAuthenticator
		autowired: false
$container->getService('facebookAuth');
$container->getService('twitterAuth');

Tagování

services:
	middleware1:
		class: App\Model\CacheMiddleware
		tags: [middleware: 100]
	middleware2:
		class: App\Model\LoggingMiddleware
		tags: [middleware: 200]
	middleware3:
		class: App\Model\ApitteMiddleware
		tags: [middleware: 300]
$names = $container->findByTag('middleware');
foreach ($names as $name => $tag) {
	// $tag = [middleware => 100]
	$container->getService($name);
}

Injectování

namespace App\Model;

class DatabaseAuthenticator
{
	/** @var App\Model\MonologLogger @inject */
	public $logger;
}
services:
	authenticator:
		class: App\Model\DatabaseAuthenticator
		inject: true

	# alternativni zapis
	- { class: App\Model\DatabaseAuthenticator, inject: true }

Extra

services:
	# vsechny parametry z kontejneru
	- App\Model\Foo(@container::parameters)

	# vsechny sluzby daneho typu
	- App\Model\Foo(@container::findByType(App\Model\Bar))

	# volani fce getenv()
	- App\Moel\Foo(::getenv(NODE_DEBUG))

Nette 3.0+

V Nette 2.4 jdou definovat služby mnoha způsoby a při troše cviku jste schopní vyřešit opravdu cokoli.

Podle aktivity v nette/di bychom v Nette 3 mohli narazit na nové vychytávky.

Autowiring pole služeb podle typu

namespace App\Model;

class FacebookAuthenticator
{
	/** @param AuthSubscriber[] $subscribers */
	public function __construct(array $subscribers) { ... }
}
services:
	- App\Mode\CacheCleanerAuthSubscriber
	- App\Model\LoggerAuthSubscriber

	- App\Model\FacebookAuthenticator( types(App\Model\AuthSubscriber) )

Autowiring pole služeb podle tagu

services:
	- { class: App\Mode\CacheCleanerAuthSubscriber, tags: [auth]}
	- { class: App\Mode\LoggerAuthSubscriber, tags: [auth]}

	- App\Model\AuthentictorMiddleware( tags(auth) )

Expandování klíče i hodnoty

parameters:
	username: user
	password: 1234

services:
	# [%username% => 1234] v Nette 2.4
	- Nette\Security\SimpleAuthenticator({%username%: %password%})
	# [user => 1234] v Nette 3.0+
	- Nette\Security\SimpleAuthenticator({%username%: %password%})

Myslím, že se máme na co těšit. Sledujte vývoj! 👀 🎉


A jak používáte nette/di vy? Napište mi to do komentářů.