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ářů.