Zend Framework - 服务管理器
-
简述
Zend Framework包括一个功能强大的服务定位器模式实现,称为 zend-服务管理器。Zend Framework广泛使用服务管理器来实现其所有功能。服务管理器为 Zend Framework提供了高级抽象。它还与Zend Framework的所有其他组件很好地集成在一起。 -
安装服务管理器
可以使用Composer工具安装服务管理器组件。composer require zendframework/zend-servicemanager
例
首先,所有服务都需要注册到服务管理器中。一旦服务注册到服务器管理器系统中,就可以随时以最小的工作量访问它。服务管理器提供了许多注册服务的选项。一个简单的例子如下 -use Zend\ServiceManager\ServiceManager; use Zend\ServiceManager\Factory\InvokableFactory; use stdClass; $serviceManager = new ServiceManager([ 'factories' => [stdClass::class => InvokableFactory::class,], ]);
上面的代码使用“Factory”选项将 stdClass 注册到系统中。现在,我们可以随时使用服务管理器的 get() 方法获取 stdClass 的实例,如下所示。use Zend\ServiceManager\ServiceManager; $object = $serviceManager->get(stdClass::class);
get() 方法共享检索到的对象,因此,多次调用 get() 方法返回的对象是同一个实例。为了每次都获取不同的实例,服务管理器提供了另一种方法,即 build() 方法。use Zend\ServiceManager\ServiceManager; $a = $serviceManager->build(stdClass::class); $b = $serviceManager->build(stdClass::class);
服务管理器注册
服务管理器提供了一组方法来注册组件。一些最重要的方法如下所述 -- 工厂方法
- 抽象工厂方法
- 初始值设定项方法
- 委托工厂方法
我们将在后续章节中详细讨论其中的每一个。 -
工厂方法
工厂基本上是任何可调用的或实现FactoryInterface(Zend\ServiceManager\Factory\FactoryInterface)的任何类。工厂接口只有一个方法 −public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
工厂接口的参数细节如下 :-
container − 它是服务管理器的基本接口。它提供了获取其他服务的选项。
-
requestedName − 它是服务名称。
-
options − 它提供了服务所需的其他选项。
让我们创建一个实现工厂接口的简单类,并了解如何注册该类。Test 类 - 要检索的对象
use stdClass; class Test { public function __construct(stdClass $sc) { // use $sc } }
Test类依赖于stdClass。TestFactory 类 - 用于初始化测试对象的类
class TestFactory implements FactoryInterface { public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { $dep = $container->get(stdClass::class); return new Test($dep); } }
TestFactory 使用容器来检索 stdClass,创建测试类的实例,然后返回它。Zend Framework 的注册和使用
现在让我们了解如何注册和使用Zend Framework。serviceManager $sc = new ServiceManager([ 'factories' => [stdClass::class => InvokableFactory::class, Test::class => TestFactory::class] ]); $test = $sc->get(Test::class);
服务管理器提供了一个名为“InvokableFactory”的特殊工厂来检索任何没有依赖关系的类。例如,可以使用可调用工厂配置 stdClass,因为 stdClass 不依赖于任何其他类。serviceManager $sc = new ServiceManager([ 'factories' => [stdClass::class => InvokableFactory::class] ]); $stdC = $sc->get(stdClass::class);
在不实现FactoryInterface或使用InvokableFactory的情况下检索对象的另一种方法是使用内联方法,如下所示。$serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class, Test::class => function(ContainerInterface $container, $requestedName) { $dep = $container->get(stdClass::class); return new Test($dep); }, ], ]);
-
-
抽象工厂方法
有时,我们可能需要创建对象,而这些对象只有在运行时才会知道。可以使用AbstractFactoryInterface处理这种情况,该接口派生自工厂接口。抽象工厂接口定义了一种方法来检查是否可以在请求的实例上创建对象。如果可以创建对象,它将使用工厂接口的__invokemethod创建对象并返回它。AbstractFactoryInterface 的签名如下 :public function canCreate(ContainerInterface $container, $requestedName)
-
初始值设定项方法
初始值设定项方法是一个特殊选项,用于为已创建的服务注入其他依赖项。它实现了InitializerInterface,唯一可用方法的签名如下 -public function(ContainerInterface $container, $instance) function(ContainerInterface $container, $instance) { if (! $instance instanceof EventManagerAwareInterface) { return; } $instance->setEventManager($container->get(EventManager::class)); }
在上面的示例中,该方法检查实例的类型是否为事件管理器软件接口。如果它是EventManagerAwareInterface的类型,则它设置事件管理器对象,否则不设置。由于该方法可能设置也可能不设置依赖项,因此它不可靠并产生许多运行时问题。 -
委托工厂方法
Zend Framework通过委托DelegatorFactoryInterface模式。它可以用来装饰服务。此函数的签名如下 −public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null );
此处,$callback负责修饰服务实例。惰性服务
惰性服务是在创建时不会完全初始化的服务之一。它们只是被引用,并且仅在真正需要时才初始化。最好的例子之一是数据库连接,可能并非在所有地方都需要它。这是一种昂贵的资源,并且具有耗时的过程来创建。Zend Framework提供从DelegatorFactoryInterface派生的LazyServiceFactory,它可以在Delegator概念和第三方代理管理器(称为ocramius代理管理器)的帮助下产生懒惰的服务。 -
插件管理器
插件管理器扩展了服务管理器,并提供了其他功能,如实例验证。Zend Framework广泛使用插件管理器。例如,所有验证服务都属于ValidationPluginManager管理器。 -
配置选项
服务管理器提供了一些选项来扩展服务管理器的功能。它们是shared,shared_by_default和aliases。如前所述,默认情况下,检索到的对象在请求的对象之间共享,我们可以使用 build() 方法来获取不同的对象。我们还可以使用shared选项来指定要共享的服务。shared_by_default与shared功能相同,只是它适用于所有服务。$serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class ], 'shared' => [ stdClass::class => false // will not be shared ], 'shared_by_default' => false, // will not be shared and applies to all service ]);
aliases选项可用于为已注册的服务提供备用名称。这既有优点也有缺点。从积极的一面来看,我们可以为服务提供替代的短名称。但是,与此同时,该名称可能会脱离上下文并引入错误。aliases' => ['std' => stdClass::class, 'standard' => 'std']