使用自定义服务定位器减少服务配置重复?
问题描述:
我的应用程序使用数据映射器模式,所以我有许多映射器类,它们都需要数据库适配器的一个实例。所以,我的服务配置的factories
截面布满了条目是这样的:使用自定义服务定位器减少服务配置重复?
'UserMapper' => function($sm) {
$mapper = new UserMapper();
$adapter = $sm->get('Zend\Db\Adapter\Adapter');
$mapper->setAdapter($adapter);
return $mapper;
},
'GroupMapper' => function($sm) {
$mapper = new GroupMapper();
$adapter = $sm->get('Zend\Db\Adapter\Adapter');
$mapper->setAdapter($adapter);
return $mapper;
},
我想去掉一些这方面锅炉板代码。我可以为这些映射器定义一个自定义服务定位器类,它可以通过提供数据库适配器来实例化任何映射器类,除非定义的工厂配置存在定义吗?
答
有两种方法可以解决这个问题。
首先是让你的映射器实现Zend\Db\Adapter\AdapterAwareInterface
,并向服务管理器添加一个初始化器,它将适配器注入到实现该接口的任何服务中。如果你这样做,所有的映射器都可以放在服务配置的密钥invokables
中,而不是每个都需要一个工厂。然后
的映射器将所有类似于此
<?php
namespace Foo\Mapper;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Adapter\AdapterAwareInterface;
// if you're using php5.4 you can also make use of the trait
// use Zend\Db\Adapter\AdapterAwareTrait;
class BarMapper implements AdapterAwareInterface;
{
// use AdapterAwareTrait;
// ..
/**
* @var Adapter
*/
protected $adapter = null;
/**
* Set db adapter
*
* @param Adapter $adapter
* @return mixed
*/
public function setDbAdapter(Adapter $adapter)
{
$this->adapter = $adapter;
return $this;
}
}
在服务管理器的配置,把你的映射器下invokables,并添加一个初始化为AdapterAware服务
return array(
'invokables' => array(
// ..
'Foo/Mapper/Bar' => 'Foo/Mapper/BarMapper',
// ..
),
'initializers' => array(
'Zend\Db\Adapter' => function($instance, $sm) {
if ($instance instanceof \Zend\Db\Adapter\AdapterAwareInterface) {
$instance->setDbAdapter($sm->get('Zend\Db\Adapter\Adapter'));
}
},
),
);
另一种方法是创建一个MapperAbstractServiceFactory
,这个答案 - >ZF2 depency injection in parent描述了你可能会这样做。
谢谢!我会进一步探索这两个选项 – 2013-05-14 09:39:44