spiechu / lazy-pimple
此包已被废弃,不再维护。未建议替代包。
为Pimple DI容器提供懒加载服务定义。
0.7
2019-04-27 11:13 UTC
Requires
- php: ^7.1
- ocramius/proxy-manager: ~1.0|~2.0
- pimple/pimple: ~2.1|~3.0
- symfony/event-dispatcher: ~3.0|~4.0
Requires (Dev)
- phpunit/phpunit: ~7.0
README
为Pimple DI容器提供懒加载服务定义。
简介
在使用Pimple DIC时,有时需要懒加载服务,并且只在需要时实例化它。此外,还有可能懒加载事件订阅者。(现在你会明白为什么 \Symfony\Component\EventDispatcher\EventSubscriberInterface
有静态接口)。
在底层,这个库使用 Proxy Manager。首先生成对象的代理。在需要实例方法调用之前,使用代理。这意味着即使是静态调用,也不需要对象的实例,而是通过代理来调用。
安装
最简单的方法是将 "spiechu/lazy-pimple": "~0.1"
添加到您的 composer.json
。
为了使懒加载工作,需要在Pimple中添加两个定义的最小配置
<?php $pimpleContainer['lazy_loading_value_holder_factory_factory'] = function(Container $container) { return (new \Spiechu\LazyPimple\Factory\LazyLoadingValueHolderFactoryFactory()) ->getFactory(); }; $pimpleContainer['lazy_service_factory'] = function(Container $container) { return new \Spiechu\LazyPimple\Factory\LazyServiceFactory($container['lazy_loading_value_holder_factory_factory']); };
为了使用ProxyManager代理缓存,LazyLoadingValueHolderFactoryFactory->getFactory()
接受写入空间的路径,其中它可以转储生成的代理类定义。您可以在页面底部的完整列表中查看如何操作。
用法
懒加载服务
使用此库,您可以轻松地懒加载Pimple服务定义,直到需要它们。
<?php // imgine awesome service is expensive and should be lazy loaded $pimpleContainer['awesome_service'] = function(Container $container) { return $container['lazy_service_factory']->getLazyServiceDefinition(AwesomeService::class, function() { return new AwesomeService(); }); };
懒加载事件订阅者
我们从典型的事件订阅者定义开始。
<?php $pimpleContainer['first_subscriber'] = function(Container $container) { // subscriber has no idea it will be lazy loaded return new FirstSubscriber($container['awesome_service']); };
现在,通过使用 \Pimple\ServiceProviderInterface
服务提供者,我们可以将订阅者转换为懒加载。
<?php $pimpleContainer->register(new LazyEventSubscriberServiceProvider( $pimpleContainer['lazy_service_factory'], // we're defining which service resolves to EventDispatcher 'event_dispatcher', [ // we're defining subscribers 'first_subscriber' => FirstSubscriber::class, ] ));
这样,只有在事件实际发生时,订阅者才会被实例化,并且调用事件处理方法。
示例Pimple服务定义(摘自我的“测试”)。
<?php use Pimple\Container; use Spiechu\LazyPimple\DependencyInjection\LazyEventSubscriberServiceProvider; use Spiechu\LazyPimple\Factory\LazyLoadingValueHolderFactoryFactory; use Spiechu\LazyPimple\Factory\LazyServiceFactory; use Spiechu\LazyPimple\FirstSubscriber; use Spiechu\LazyPimple\Service\AnotherService; use Spiechu\LazyPimple\Service\AwesomeService; use Spiechu\LazyPimple\Service\EventEmittingService; use Symfony\Component\EventDispatcher\EventDispatcher; // prevent leaking any variables into global namespace return call_user_func(function() { require_once './vendor/autoload.php'; $pimpleContainer = new Container(); $pimpleContainer['proxy_manager_cache_target_dir'] = function(Container $container) { $targetDir = __DIR__ . '/proxy_cache_dir'; if (!is_dir($targetDir)) { mkdir($targetDir, 0775, true); } return $targetDir; }; $pimpleContainer['lazy_loading_value_holder_factory_factory'] = function(Container $container) { return (new LazyLoadingValueHolderFactoryFactory()) ->getFactory($container['proxy_manager_cache_target_dir']); }; $pimpleContainer['lazy_service_factory'] = function(Container $container) { return new LazyServiceFactory($container['lazy_loading_value_holder_factory_factory']); }; $pimpleContainer['event_dispatcher'] = function(Container $container) { return new EventDispatcher(); }; // imgine awesome service is expensive and should be lazy loaded $pimpleContainer['awesome_service'] = function(Container $container) { return $container['lazy_service_factory']->getLazyServiceDefinition(AwesomeService::class, function() { return new AwesomeService(); }); }; $pimpleContainer['another_service'] = function(Container $container) { // this one will receive proxy object return new AnotherService($container['awesome_service']); }; $pimpleContainer['event_emitting_service'] = function(Container $container) { return new EventEmittingService($container['event_dispatcher']); }; $pimpleContainer['first_subscriber'] = function(Container $container) { // subscriber has no idea it will be lazy loaded return new FirstSubscriber($container['awesome_service']); }; $pimpleContainer->register(new LazyEventSubscriberServiceProvider( $pimpleContainer['lazy_service_factory'], // we're defining which service resolves to EventDispatcher 'event_dispatcher', [ // we're defining subscribers 'first_subscriber' => FirstSubscriber::class, ] )); return $pimpleContainer; });