父级中的ZF2依赖注入

时间:2013-03-09 12:41:15

标签: php dependency-injection zend-framework2

我想从控制器调用方法SteeringWheelMapper-> fetchCarBrandList()。 这现在很好用,但是有一个问题。

SteeringWheelMapper扩展了AbstractWebServiceMapper,它有一个构造方法,需要一个\ Zend \ Http \ Client实例。

正如您在我的module.config.php文件中看到的,我使用“工厂”来实例化我的SteeringWheelMapper。 供应商有多个产品,因此我将不得不构建多个映射器。在目前的情况下,这意味着我必须为扩展AbstractWebServiceMapper的每个映射器的工厂配置添加一个键。

例如,当我想添加ExhaustMapper时,我必须添加

SupplierName\Mapper\Exhaust => function ($serviceMapper) {
    $httpClient => new \Zend\Http\Client;

    return new SupplierName\Mapper\ExhaustMapper($httpClient);
}

现在我正在重复自己,因为我还必须为SupplierName \ Mapper \ SteeringWheelMapper执行此操作。

我认为应该有办法为所有映射器创建一个工厂,而不是添加到工厂配置中的新密钥。 我的想法是对的吗? 有没有人建议我该怎么做?

请参阅以下代码。

我正在使用ZF2并使用此设置: /供应商

  • SupplierName

    • 配置
      • module.config.php
    • 日志
      • log.log
    • SRC
      • SupplierName
        • 实体
          • AbstractEntity.php
          • SteeringWheelEntity.php
        • 映射器
          • AbstractWebServiceMapper.php
          • SteeringWheelMapper.php

    $ steeringWheelMapper = $ this-> getServiceLocator() - > get('SupplierName \ Mapper \ SteeringWheel'); $ carBrandList = $ steeringWheelMapper-> fetchCarBrandsList();

SteeringWheelMapper.php

<?php

namespace SupplierName\Mapper;

class SteeringWheelMapper extends AbstractWebServiceMapper
{   
    public function fetchCarBrandList()
    {
        // Code for request

        // Dispatch HTTP request
        $this->dispatch();
    }
}

我的SupplierName / config / module.config.php如下所示:

<?php

return array(
    'service_manager' => array(
        'factories' => array(
            'SupplierName\Mapper\SteeringWheel' => function ($serviceManager) {
                $httpClient = new \Zend\Http\Client;

                return new SupplierName\Mapper\SteeringWheelMapper($httpClient);
            },
        ),
    ),
    'supplier_name' => array(
        'api' => array(
            'url' => 'http://api.example.com',
        ),
        'log' => array(
            'file_location' => __DIR__ . '/../log/log.log',
        ),
    ),
);

2 个答案:

答案 0 :(得分:1)

你实际谈论的是一个抽象工厂,服务经理支持这个概念,但是你需要自己编写,这里有一个例子,假设所有的地图制作者都以SupplierName\Mapper开头

<?php
namespace SupplierName\Services;

use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class MapperAbstractFactory implements AbstractFactoryInterface
{
    public function canCreateServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName)
    {
        if (0 === strpos($requestedName, 'SupplierName\\Mapper') && class_exists($requestedName)){
            return true;
        }
        return false;
    }

    public function createServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName)
    {
        $httpClient = new \Zend\Http\Client;

        return new $requestedName($httpClient);
    }
}

在你的服务配置中,添加一个抽象工厂密钥,以及抽象工厂的fqcn,希望每当你调用$sm->get('SupplierName\Mapper\SomeClass');提供类时,你都会得到一个返回的组合实例

public function getServiceConfig()
{       
    return array(
        'abstract_factories' => array(    
            'SupplierName\Services\MapperAbstractFactory'
        ),
    );
}

答案 1 :(得分:1)

最终工作解决方案:

<?php
// module/Application/src/Application/Controller/IndexController.php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\I18n\Translator\Translator;

class IndexController extends AbstractActionController
{
    protected $translator;

    public function __construct(Translator $translator)
    {
        $this->translator = $translator;
    }

    public function indexAction()
    {                
        $steeringWheelMapper = $this->getServiceLocator()->get('SupplierName\Mapper\SteeringWheel');
        $carBrandList = $steeringWheelMapper->fetchCarBrandList();

        return new ViewModel();
    }

}

<?php
// vendor/SupplierName/src/SupplierName/Module.php

namespace SupplierName;

class Module
{    
    public function getConfig()
    {
        return include __DIR__ . '/../../config/module.config.php';
    }

    public function getServiceConfig()
    {   
        return array(
            'abstract_factories' => array(    
                'SupplierName\Mapper\MapperAbstractFactory'
            ),
        );
    }

    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__,
                ),
            ),
        );
    }

}

<?php
// vendor/SupplierName/src/SupplierName/Mapper/SteeringWheelMapper.php

namespace SupplierName\Mapper;

class SteeringWheelMapper extends AbstractWebServiceMapper
{   
    public function fetchCarBrandList()
    {
        $this->dispatch();
    }
}

<?php
// vendor/SupplierName/src/SupplierName/Mapper/AbstractWebServiceMapper.php

namespace SupplierName\Mapper;

use \Zend\Http\Client;

class AbstractWebServiceMapper
{
    public function __construct(Client $client)
    {

    }

    public function dispatch()
    {       

    }

}

<?php
// vendor/SupplierName/src/SupplierName/Mapper/MapperAbstractFactory.php
namespace SupplierName\Mapper;

use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

use \Zend\Http\Client;

class MapperAbstractFactory implements AbstractFactoryInterface
{
    public function canCreateServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName)
    {    
        if (0 === strpos($requestedName, 'SupplierName\Mapper')) {
            $requestedName .= 'Mapper';

            if (class_exists($requestedName)) {
                return true;
            }
        }

        return false;
    }

    public function createServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName)
    {
        $requestedName .= 'Mapper';

        $httpClient = new Client();

        return new $requestedName($httpClient);
    }
}