Zend Framework - 服务管理器

Zend Framework 包含一个强大的服务定位器模式实现,称为 zend-servicemanager。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) 的类。

FactoryInterface 有一个方法 −

public function __invoke(ContainerInterface $container, $requestedName, array
$options = null)

FactoryInterface 的参数详细信息如下−

  • container (ContainerInterface) − 它是 ServiceManager 的基本接口。它提供了获取其他服务的选项。

  • requestedName − 它是服务名称。

  • options − 它提供服务所需的其他选项。

让我们创建一个实现 FactoryInterface 的简单类,并了解如何注册该类。

类测试 - 要检索的对象

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 框架的注册和使用

现在让我们了解如何注册和使用 Zend 框架。

serviceManager $sc = new ServiceManager([ 
   'factories' => [stdClass::class => InvokableFactory::class, 
      Test::class => TestFactory::class] 
]); 
$test = $sc->get(Test::class);

服务管理器提供了一个名为 InvokableFactory 的特殊工厂来检索任何没有依赖关系的类。例如,可以使用 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); 
      }, 
   ], 
]);

抽象工厂方法

有时,我们可能需要创建对象,而这些对象我们只能在运行时才知道。这种情况可以使用从 FactoryInterface 派生的 AbstractFactoryInterface 来处理。

AbstractFactoryInterface 定义了一个方法来检查是否可以在请求的实例上创建对象。如果可以创建对象,它将使用 FactoryInterface 的 __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 类型。如果是 EventManagerAwareInterface 类型,则设置事件管理器对象,否则不设置。由于该方法可能会或可能不会设置依赖项,因此它不可靠并且会产生许多运行时问题。

委托人工厂方法

Zend Framework 通过 DelegatorFactoryInterface 支持委托人模式。它可用于装饰服务。

此函数的签名如下 −

public function __invoke(ContainerInterface $container,
    $name, callable $callback, array $options = null
);

此处,$callback 负责修饰服务实例。

惰性服务

惰性服务是那些在创建时不会完全初始化的服务之一。它们只是被引用,并且只在真正需要时才初始化。最好的例子之一是数据库连接,它可能不是在所有地方都需要。它是一种昂贵的资源,并且创建过程也很耗时。Zend 框架提供了从 DelegatorFactoryInterface 派生的 LazyServiceFactory,它可以在 Delegator 概念和第三方代理管理器(称为 ocramius 代理管理器)的帮助下生成惰性服务。

插件管理器

插件管理器扩展了服务管理器并提供实例验证等附加功能。 Zend Framework 广泛使用插件管理器。

例如,所有验证服务都属于 ValidationPluginManager

配置选项

服务管理器提供了一些选项来扩展服务管理器的功能。它们是 shared、shared_by_defaultaliases。正如我们前面所讨论的,检索到的对象默认在请求的对象之间共享,我们可以使用 build() 方法获取不同的对象。我们还可以使用 shared 选项来指定要共享的服务。shared_by_defaultshared 功能相同,只是它适用于所有服务。

$serviceManager = new ServiceManager([ 
   'factories' => [ 
      stdClass::class => InvokableFactory::class 
   ], 
   'shared' => [ 
      stdClass::class => false // 不会共享
   ], 
   'shared_by_default' => false, // 不会共享且适用于所有服务
]);

别名选项可用于为已注册的服务提供备用名称。这既有优点也有缺点。从积极的一面来看,我们可以为服务提供备用的简称。但与此同时,该名称可能会脱离上下文并引入错误。

aliases' => ['std' => stdClass::class, 'standard' => 'std']