0

我想从控制器调用 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,并使用此设置:/vendor

  • 供应商名称

    • 配置
      • 模块.config.php
    • 日志
      • 日志.log
    • 源代码
      • 供应商名称
        • 实体
          • 抽象实体.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',
        ),
    ),
);
4

2 回答 2

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);
    }
}
于 2013-03-10T12:03:36.700 回答
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'
        ),
    );
}
于 2013-03-09T13:19:27.020 回答