来自没有控制器的模块的 ZF2 配置 [英] ZF2 config from module with no controllers

查看:17
本文介绍了来自没有控制器的模块的 ZF2 配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在构建一个模块以在多个项目中用作可重用的库,但是由于它是一个库,因此不需要控制器.例如,我想做的是为 Marketo soap API 创建一个 zf2 模块.用户在/ROOT/config/autoload/local.php 中添加他们的密钥和 wsdl 位置.配置将包括类似 'marketo'=>array(),

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

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

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

然而,我可以将所有这些都放在一个 ini 文件中,但我更愿意让它与 zf2 中的其他所有内容的配置方式相似.

总而言之,我想获得合并的 zend 配置的数组键,以便在类中使用,例如...

class Marketo{私人 $key;私人 $pass;公共函数 __construct(){$c = \Zend\Config\Config('marketo);$this->key = $c['key'];$this->pass = $c['pass'];}}

============ 从 ZF 2.1.1 开始,根据以下答案完全有效的解决方案 ==============>

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

模块- 应用程序/* 带有 IndexController 的标准设置 */- Cyber​​source/* 要添加的新模块 */+ 配置- 模块.config.php+ 来源+ 网络资源+ 客户- 客户端.php+ 服务工厂- ClientServiceFactory.php- 模块.php- autoload_classmap.php

module.config.php

返回数组('service_manager' =>大批('工厂' =>大批('Cyber​​source\Client\Client' =>'网络资源\服务工厂\客户端服务工厂',)),'网络资源' =>大批('端点' =>'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor',//测试环境'WSDL' =>'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/Cyber​​SourceTransaction_1.80.wsdl','TXKey' =>'','MerchID' =>'',),);

Client.php

namespace Cyber​​source\Client;类客户{私人 $config;公共函数 __construct($config) {$this->config = $config;}公共函数 getConfig() {返回 $this->config;}}

ClientServiceFactory.php

namespace Cyber​​source\ServiceFactory;使用 Cyber​​source\Client\Client;使用 Zend\ServiceManager\FactoryInterface;使用 Zend\ServiceManager\ServiceLocatorInterface;类 ClientServiceFactory 实现 FactoryInterface {公共函数 createService(ServiceLocatorInterface $serviceLocator) {$config = $serviceLocator->get('Config');返回新客户端($config['cybersource']);}}

Module.php

namespace Cyber​​source;使用 Zend\ModuleManager\Feature\ConfigProviderInterface;类模块实现 ConfigProviderInterface {公共函数 getAutoloaderConfig() {返回数组('Zend\Loader\ClassMapAutoloader' =>大批(__DIR__ .'/autoload_classmap.php',));}公共函数 getConfig() {返回包括 __DIR__ .'/config/module.config.php';}}

autoload_classmap.php

__DIR__ .'/Module.php','Cyber​​source\Client\Client' =>__DIR__ .'/src/Cyber​​source/Client/Client.php','Cyber​​source\ServiceFactory\ClientServiceFactory' =>__DIR__ .'/src/ServiceFactory/ClientServiceFactory.php',);

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

getServiceLocator()->get('Cyber​​source\Client\Client');$conf = $c->getConfig();var_dump($conf);返回新的 ViewModel();}}

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

再次感谢大家的帮助.

解决方案

你可能会像下面这样定义一个模块:

<?php命名空间市场;使用 Zend\ModuleManager\Feature\ConfigProviderInterface;类 Module 实现了 ConfigProviderInterface{公共函数 getConfig(){返回数组('service_manager' =>大批('工厂' =>大批('Marketo\Client\Client' =>'Marketo\ServiceFactory\ClientServiceFactory',),),'市场' =>大批('键' =>'默认','通过' =>'默认',),);}}

注意:我更喜欢使用 getConfig 而不是 getServiceConfig,因为它更灵活(可覆盖),并且在您设置应用程序时会缓存方法调用.

然后是 Marketo\ServiceFactory\ClientServiceFactory:

<?php命名空间 Marketo\ServiceFactory;使用 Marketo\Client\Client;使用 Zend\ServiceManager\FactoryInterface;使用 Zend\ServiceManager\ServiceLocatorInterface;类 ClientServiceFactory 实现 FactoryInterface{公共函数 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返回数组('市场' =>大批('键' =>'市场管理员','通过' =>'Pa$$w0rd',),);

这很重要,因为你不应该重新分发你的 keypass,所以把这个文件放到 .gitignoresvn:忽略!

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

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

I'm currently in the process of building a module to serve as a re-usable library throughout multiple projects, however due to it being a library there isn't a need for a controller. What I'm trying to do for instance is create a zf2 module for Marketo soap API for instance. User adds their keys and wsdl location in /ROOT/config/autoload/local.php. The configuration would include something like 'marketo'=>array(),

Now the problem that I'm having is I want to give myself and others using the module the ability to do something like...

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

and inside the \Marketo\Client\Client() class have the constructor read the array key of $config['marketo'];

I could however put all of this in an ini file, but I would prefer to keep it similar to how everything else in zf2 is configuration wise.

So to summarize I would like to get an array key of the merged zend configuration to use inside the class something like...

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

============ Fully working solution as of ZF 2.1.1 per the answers below =============

Module structure looks as follows (Using a new example so I could start fresh) + indicates directory name - indicates filename

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',
);

Once the module has been activated in the application.config.php I could then use it in my IndexController on my Application Module by using:

<?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();
    }

}

The above controller output would dump the output of the configuration as I added a function called getConfig() to the Client class for display / testing purposes.

Thanks again for all the help.

解决方案

You would probably define a Module like following:

<?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',
            ),
        );
    }
}

Note: I preferred to use getConfig over getServiceConfig since it is more flexible (overrideable) and the method call is cached when you setup your application to do so.

Then the 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']);
    }
}

After that, you will be able to pull the Marketo client from the service locator by calling following (for example in controllers):

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

At this point, your Marketo\Client\Client is anyway built with key and pass both set to DEFAULT.

Let's go on and override this by creating a config/autoload/marketo.local.php file (in your application root, not in the module!):

<?php

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

This is VERY important since you should never redistribute your key and pass, so put this file into .gitignore or svn:ignore!

So basically what we did here is:

  1. Setup service manager configuration to use a service factory to instantiate our Marketo client
  2. Setup the service factory to use merged configuration (service name: 'config') to instantiate the Marketo client
  3. Add local configuration for the actual application instance
  4. Retrieve the Marketo service via service locator.

这篇关于来自没有控制器的模块的 ZF2 配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆