我有两个例子,我希望使用服务管理器来获取服务并让它通过配置来解决依赖关系,除了一个可变的依赖/参数(伪代码因为我意识到'get'只允许一个参数):
在控制器中,从数据库中获取实体:
$sm = $this->getServiceLocator();
$myObject = $sm->get('Model', $id);
mapper中的(服务管理器应该获得相应的适配器):
$sm = $this->getServiceLocator();
$tableGateway = $sm->get('TableGateway', $table);
实现这一目标的最佳做法是什么?
答案 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');