2013-05-14 119 views
0

我的应用程序使用数据映射器模式,所以我有许多映射器类,它们都需要数据库适配器的一个实例。所以,我的服务配置的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; 
}, 

我想去掉一些这方面锅炉板代码。我可以为这些映射器定义一个自定义服务定位器类,它可以通过提供数据库适配器来实例化任何映射器类,除非定义的工厂配置存在定义吗?

回答

4

有两种方法可以解决这个问题。

首先是让你的映射器实现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描述了你可能会这样做。

+0

谢谢!我会进一步探索这两个选项 – 2013-05-14 09:39:44