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

1 回答 1

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;
    }

}

在您的服务管理器配置中,将您的映射器放在可调用对象下,并为 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 依赖注入在父项中描述了您可能如何做到这一点。

于 2013-05-14T09:14:25.853 回答