来自没有控制器的模块的 ZF2 配置 [英] ZF2 config from module with no controllers
问题描述
我目前正在构建一个模块以在多个项目中用作可重用的库,但是由于它是一个库,因此不需要控制器.例如,我想做的是为 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 的标准设置 */- Cybersource/* 要添加的新模块 */+ 配置- 模块.config.php+ 来源+ 网络资源+ 客户- 客户端.php+ 服务工厂- ClientServiceFactory.php- 模块.php- autoload_classmap.php
module.config.php
返回数组('service_manager' =>大批('工厂' =>大批('Cybersource\Client\Client' =>'网络资源\服务工厂\客户端服务工厂',)),'网络资源' =>大批('端点' =>'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor',//测试环境'WSDL' =>'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.80.wsdl','TXKey' =>'','MerchID' =>'',),);
Client.php
namespace Cybersource\Client;类客户{私人 $config;公共函数 __construct($config) {$this->config = $config;}公共函数 getConfig() {返回 $this->config;}}
ClientServiceFactory.php
namespace Cybersource\ServiceFactory;使用 Cybersource\Client\Client;使用 Zend\ServiceManager\FactoryInterface;使用 Zend\ServiceManager\ServiceLocatorInterface;类 ClientServiceFactory 实现 FactoryInterface {公共函数 createService(ServiceLocatorInterface $serviceLocator) {$config = $serviceLocator->get('Config');返回新客户端($config['cybersource']);}}
Module.php
namespace Cybersource;使用 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','Cybersource\Client\Client' =>__DIR__ .'/src/Cybersource/Client/Client.php','Cybersource\ServiceFactory\ClientServiceFactory' =>__DIR__ .'/src/ServiceFactory/ClientServiceFactory.php',);
在 application.config.php 中激活模块后,我可以在我的应用程序模块上的 IndexController 中使用它:
getServiceLocator()->get('Cybersource\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
无论如何都是使用 key
和 pass
构建的,它们都设置为 DEFAULT代码>.
让我们继续并通过创建一个 config/autoload/marketo.local.php
文件(在您的应用程序根目录中,而不是在模块中!)来覆盖它:
<?php返回数组('市场' =>大批('键' =>'市场管理员','通过' =>'Pa$$w0rd',),);
这很重要,因为你不应该重新分发你的 key
和 pass
,所以把这个文件放到 .gitignore
或 svn:忽略
!
所以基本上我们在这里做的是:
- 设置服务管理器配置以使用服务工厂来实例化我们的 Marketo 客户端
- 设置服务工厂以使用合并配置(服务名称:
'config'
)来实例化 Marketo 客户端 - 为实际应用实例添加本地配置
- 通过服务定位器检索 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:
- Setup service manager configuration to use a service factory to instantiate our Marketo client
- Setup the service factory to use merged configuration (service name:
'config'
) to instantiate the Marketo client - Add local configuration for the actual application instance
- Retrieve the Marketo service via service locator.
这篇关于来自没有控制器的模块的 ZF2 配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!