来自无控制器模块的ZF2配置


ZF2 config from module with no controllers

我目前正在构建一个模块,作为多个项目中的可重用库,但由于它是一个库,因此不需要控制器。例如,我试图做的是为Marketo soap API创建一个zf2模块。用户在/ROOT/config/autoload/local.php中添加他们的密钥和wsdl位置

现在我遇到的问题是,我想让自己和其他使用该模块的人能够做一些事情,比如。。。

$marketo = new 'Marketo'Client'Client();

并且在''Marketo''Client''Client()类中,让构造函数读取$config的数组键['Marketo'];

然而,我可以将所有这些都放在一个ini文件中,但我更愿意将其与zf2中的其他配置类似。

总之,我想获得一个合并的zend配置的数组键,以便在类内部使用,比如。。。

class Marketo{
    private $key;
    private $pass;
    public function __construct(){
        $c = 'Zend'Config'Config('marketo);
        $this->key = $c['key'];
        $this->pass = $c['pass'];
    }
}

================根据以下答案,ZF 2.1.1的完整工作解决方案================

模块结构如下(使用一个新的例子,这样我就可以重新开始)+表示目录名-表示文件名

modules
  - Application /* Standard setup with an IndexController */
  - Cybersource /* The new module to be added */
      + config
         - module.config.php
      + src
         + Cybersource
            + Client
               - Client.php
            + ServiceFactory
               - ClientServiceFactory.php
      - Module.php
      - autoload_classmap.php

module.config.php

return array(
    'service_manager' => array(
        'factories' => array(
            'Cybersource'Client'Client' => 'Cybersource'ServiceFactory'ClientServiceFactory',
        )
    ),
    'cybersource' => array(
        'Endpoint' => 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor', // test environment
        'WSDL' => 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.80.wsdl',
        'TXKey' => '',
        'MerchID' => '',
    ),
);

Client.php

namespace Cybersource'Client;
class Client {
    private $config;
    public function __construct($config) {
        $this->config = $config;
    }
    public function getConfig() {
        return $this->config;
    }
}

ClientServiceFactory.php

namespace Cybersource'ServiceFactory;
use Cybersource'Client'Client;
use Zend'ServiceManager'FactoryInterface;
use Zend'ServiceManager'ServiceLocatorInterface;
class ClientServiceFactory implements FactoryInterface {
    public function createService(ServiceLocatorInterface $serviceLocator) {
        $config = $serviceLocator->get('Config');
        return new Client($config['cybersource']);
    }
}

Module.php

namespace Cybersource;
use Zend'ModuleManager'Feature'ConfigProviderInterface;
class Module implements ConfigProviderInterface {
    public function getAutoloaderConfig() {
        return array(
            'Zend'Loader'ClassMapAutoloader' => array(
                __DIR__ . '/autoload_classmap.php',
            )
        );
    }
    public function getConfig() {
        return include __DIR__ . '/config/module.config.php';
    }
}

autoload_classmap.php

<?php
// Generated by ZF2's ./bin/classmap_generator.php
return array(
    'Cybersource'Module'                              => __DIR__ . '/Module.php',
    'Cybersource'Client'Client'                       => __DIR__ . '/src/Cybersource/Client/Client.php',
    'Cybersource'ServiceFactory'ClientServiceFactory' => __DIR__ . '/src/ServiceFactory/ClientServiceFactory.php',
);

模块在application.config.php中激活后,我可以在应用程序模块的IndexController中使用它,方法是:

<?php

namespace Application'Controller;
use Zend'Mvc'Controller'AbstractActionController;
use Zend'View'Model'ViewModel;
class IndexController extends AbstractActionController {
    public function indexAction() {
        $c = $this->getServiceLocator()->get('Cybersource'Client'Client');
        $conf = $c->getConfig();
        var_dump($conf);
        return new ViewModel();
    }
}

上面的控制器输出将转储配置的输出,因为我向Client类添加了一个名为getConfig()的函数,用于显示/测试目的。

再次感谢您的帮助。

您可能会定义如下模块:

<?php
namespace Marketo;
use Zend'ModuleManager'Feature'ConfigProviderInterface;
class Module implements ConfigProviderInterface
{
    public function getConfig()
    {
        return array(
            'service_manager' => array(
                'factories' => array(
                    'Marketo'Client'Client' => 'Marketo'ServiceFactory'ClientServiceFactory',
                ),
            ),
            'marketo' => array(
                'key'  => 'DEFAULT',
                'pass' => 'DEFAULT',
            ),
        );
    }
}

注意:我更喜欢使用getConfig而不是getServiceConfig,因为它更灵活(可重写),并且当您设置应用程序时,方法调用是缓存的。

然后Marketo'ServiceFactory'ClientServiceFactory:

<?php
namespace Marketo'ServiceFactory;
use Marketo'Client'Client;
use Zend'ServiceManager'FactoryInterface;
use Zend'ServiceManager'ServiceLocatorInterface;
class ClientServiceFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $config = $serviceLocator->get('Config');
        return new Client($config['marketo']['key'], $value['marketo']['pass']);
    }
}

之后,您将能够通过调用以下命令(例如在控制器中)从服务定位器中提取Marketo客户端:

$marketoClient = $this->getServiceLocator()->get('Marketo'Client'Client');

此时,您的Marketo'Client'Client无论如何都是在keypass都设置为DEFAULT的情况下构建的。

让我们继续并通过创建一个config/autoload/marketo.local.php文件来覆盖它(在应用程序根目录中,而不是在模块中!):

<?php
return array(
    'marketo' => array(
        'key'  => 'MarketoAdmin',
        'pass' => 'Pa$$w0rd',
    ),
);

这一点非常重要,因为您永远不应该重新分发keypass,所以请将此文件放入.gitignoresvn:ignore

所以基本上我们在这里做的是:

  1. 设置服务管理器配置以使用服务工厂实例化我们的Marketo客户端
  2. 将服务工厂设置为使用合并配置(服务名称:'config')来实例化Marketo客户端
  3. 为实际应用程序实例添加本地配置
  4. 通过服务定位器检索Marketo服务

您应该定义一个ServiceFactory来创建您的Client。ServiceFactory可以获得合并的模块配置,并在客户端上进行设置。现在您已经有了干净的分离,并且您的类甚至可以在没有Zend''Config的情况下重用。如果您有很多配置选项,您可以创建一个单独的配置类来扩展'Zend'StdLib'AbstractOptions,并将其传递给您的客户端。

namespace Marketo'Service;
class ClientServiceFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        //Get the merged config of all modules
        $configuration = $serviceLocator->get('Config');
        $configuration = $configuration['marketo'];
        $client = new 'Marketo'Client'Client($configuration['key'], $configuration['pass']);
    }
}

现在在服务定位器中注册您的客户端工厂。在module.config.phpModule.php 中执行此操作

public function getServiceConfig()
{
    return array('factories' => array(
        'marketo_client' => 'Marketo'Service'ClientServiceFactory'
    );
}

用户现在可以从ServiceManager获取您的客户端。所有配置都设置整齐。

$sm->get('marketo_client');