ZF2通过附加参数从服务管理器获取服务

时间:2012-12-27 12:34:37

标签: service zend-framework2

我有两个例子,我希望使用服务管理器来获取服务并让它通过配置来解决依赖关系,除了一个可变的依赖/参数(伪代码因为我意识到'get'只允许一个参数):

在控制器中,从数据库中获取实体:

$sm = $this->getServiceLocator();
$myObject = $sm->get('Model', $id);
mapper中的

(服务管理器应该获得相应的适配器):

$sm = $this->getServiceLocator();
$tableGateway = $sm->get('TableGateway', $table);

实现这一目标的最佳做法是什么?

2 个答案:

答案 0 :(得分:1)

据我所知,这不是直接可行的,但我在某处读到了这种情况下的初始化器。

初始化程序可以是任何实现InitializerInterface的类,它有一个方法initialize(),用对象(Ex.instance of Model)和服务管理器实例调用initialize()方法,你需要为每个类写入条件你的对象需要初始化。在构建初始化程序类之后,您需要在服务管理器配置(module.config.php)或getServiceConfig()方法中包含条目

虽然没有完全覆盖您的问题,但可能有助于朝着正确的方向前进

修改

实现这一目标的最佳做法是什么?

回答这个问题

如果您的对象没有依赖关系,您可以将其视为

$myObject = new Model();
$myObject->find($id); which would initialize the model

如果您的模型具有依赖关系,并且如果您需要在开发阶段稍后将Model替换为其他对象,则可以使用servicelocator的服务工厂配置隔离对象创建过程,以实现此定义getServicConfig中的服务( )Module.php中的方法(您也可以定义自己的工厂代码并在配置中引用它,但在大多数用例中简单的工厂定义就足够了)

public function getServiceConfig(){
    return array(
        'factories' => array(
            'Model' =>  function(ServiceLocatorInterface $sm) {
                return new Model($dependency1, $dependency2...);
            },
        ),
    );
}

然后模型访问代码将是

$myObject = $this->serviceLocator()->get('Model');
$myObject->find($id); which would initialize the model

最佳实践是定义一个包含find($ id)的接口以及需要调用的所有其他方法,并在Model类中实现此接口,这样您就可以将工厂代码替换为实现的任何其他对象界面,您无需触摸Model对象的使用代码。

对于用例2,我假设您尝试重用或减少重复代码。如果您有一组有限的组合,您可以像下面那样实现它

像这样定义服务工厂

public function getServiceConfig(){
    return array(
        'factories' => array(
            'Model/table1' =>  function(ServiceLocatorInterface $sm) {
                return new TableGateway('table1', $sm->get('db'));
            },
            'Model/table2' =>  function(ServiceLocatorInterface $sm) {
                return new TableGateway('table2', $sm->get('db'));
            },
        .
        .
        .
        .
        ),
    );
}    

将table1作为

访问
$tableGateway = $this->serviceLocator()->get('Model/table1');

注意:'Model / table1'是命名空间并避免覆盖config,内部'/'将被服务管理器删除,并且名称将在注册和获取时以小写形式显示。

Zend \ ServiceManager \ ServiceManager将其所谓的canonicalNames存储在受保护的属性中。这是一个映射到规范名称的命名空间数组,这些命名空间是斜杠被剥离并变为小写的。

答案 1 :(得分:1)

您所描述的并不是ServiceManager的用例。就像它在锡上说的那样,它是一个管理服务的系统。使用它来抓取单个实体并不合适。相反,使用servicemanager获取存储库,并使用该存储库来获取实体:

$entity = $this->getServiceLocator()->get('FooRepository')->find($id);

在你的第二个例子中,似乎你有一些创建TableGateways的Factory。一个明智的做法是:

$gateway = $this->getServiceLocator()->get('TableGatewayFactory')->get($table);

或者,您可以为每个网关定义单独的服务:

$gateway = $this->getServiceLocator()->get('FooTableGateway');