简体   繁体   English

ZF2配置来自没有控制器的模块

[英]ZF2 config from module with no controllers

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. 例如,我正在尝试做的是为Marketo soap API创建一个zf2模块。 User adds their keys and wsdl location in /ROOT/config/autoload/local.php. 用户在/ROOT/config/autoload/local.php中添加其密钥和wsdl位置。 The configuration would include something like 'marketo'=>array(), 配置包括'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']; 在\\ Marketo \\ Client \\ Client()类中,构造函数读取$ 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. 然而,我可以将所有这些放在一个ini文件中,但我更喜欢将它与zf2中的其他所有内容类似。

So to summarize I would like to get an array key of the merged zend configuration to use inside the class something like... 总结一下,我想获得一个合并的zend配置的数组键,以便在类中使用...

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 ============= ============根据以下答案,从ZF 2.1.1开始全面运作解决方案=============

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 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 Client.php

namespace Cybersource\Client;

class Client {

    private $config;

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

    public function getConfig() {
        return $this->config;
    }

}

ClientServiceFactory.php 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 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 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: 一旦在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();
    }

}

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. 上面的控制器输出将转储配置的输出,因为我将一个名为getConfig()的函数添加到Client类以进行显示/测试。

Thanks again for all the help. 再次感谢所有的帮助。

You should define a ServiceFactory to create your Client . 您应该定义ServiceFactory来创建您的Client The ServiceFactory can get the merged module configuration and set it on your Client. ServiceFactory可以获取合并的模块配置并在您的客户端上进行设置。 You have clean seperation now and your class is even reusable without Zend\\Config at all. 你现在有了干净的分离,你的课程甚至可以在没有Zend \\ Config的情况下重复使用。 If you have a lot of configuration options you could create a seperate configuration class extending \\Zend\\StdLib\\AbstractOptions and pass this to your client. 如果您有许多配置选项,则可以创建一个单独的配置类,扩展\\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']);
    }
}

Now register your client factory in the service locator. 现在在服务定位器中注册您的客户端工厂。 Do this in the module.config.php or Module.php module.config.phpModule.php执行此Module.php

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

Users can now get your client from the ServiceManager. 用户现在可以从ServiceManager获取客户端。 All configuration is neatly setup. 所有配置都整齐地设置。

$sm->get('marketo_client');

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. 注意:我更喜欢在getServiceConfig上使用getConfig ,因为它更灵活(可重写),并且在设置应用程序时会缓存方法调用。

Then the Marketo\\ServiceFactory\\ClientServiceFactory : 然后是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): 之后,您可以通过调用以下内容(例如在控制器中)从服务定位器中提取Marketo客户端:

$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 . 此时,您的Marketo\\Client\\Client无论如何都是使用key构建的, pass两者都设置为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!): 让我们继续并通过创建config/autoload/marketo.local.php文件来覆盖它(在您的应用程序根目录中,而不是在模块中!):

<?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 ! 这非常重要,因为你永远不应该重新分发你的keypass ,所以把这个文件放到.gitignoresvn:ignore

So basically what we did here is: 基本上我们在这里做的是:

  1. Setup service manager configuration to use a service factory to instantiate our Marketo client 设置服务管理器配置以使用服务工厂来实例化我们的Marketo客户端
  2. Setup the service factory to use merged configuration (service name: 'config' ) to instantiate the Marketo client 设置服务工厂以使用合并配置(服务名称: 'config' )来实例化Marketo客户端
  3. Add local configuration for the actual application instance 添加实际应用程序实例的本地配置
  4. Retrieve the Marketo service via service locator. 通过服务定位器检索Marketo服务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM