В настоящее время я собираюсь создать модуль для использования в качестве повторно используемой библиотеки во многих проектах, однако из-за того, что он является библиотекой, нет необходимости в контроллере. Например, я пытаюсь создать модуль zf2 для API-интерфейса Marketo. Пользователь добавляет свои ключи и местоположение wsdl в /ROOT/config/autoload/local.php. Конфигурация будет включать нечто вроде «marketo» => array (),
Теперь проблема, с которой я сталкиваюсь, это то, что я хочу дать себе и другим, используя модуль возможность делать что-то вроде …
$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(); } }
Вышеуказанный выход контроллера будет выгружать выходные данные конфигурации, поскольку я добавил функцию класса getConfig () в класс Client для отображения / тестирования.
Еще раз спасибо всем за помощь.
Вероятно, вы бы определили модуль следующим образом:
<?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
в любом случае построен с key
и pass
оба значения в DEFAULT
.
Давайте перейдем к этому и config/autoload/marketo.local.php
файл config/autoload/marketo.local.php
(в корне вашего приложения, а не в модуле!):
<?php return array( 'marketo' => array( 'key' => 'MarketoAdmin', 'pass' => 'Pa$$w0rd', ), );
Это ОЧЕНЬ важно, так как вы никогда не должны перераспределять свой key
и pass
, поэтому поместите этот файл в .gitignore
или svn:ignore
!
Итак, в основном мы здесь сделали:
'config'
) для создания экземпляра клиента Marketo Вы должны определить ServiceFactory
для создания своего Client
. ServiceFactory может получить конфигурацию объединенного модуля и установить его на вашем Клиенте. Теперь у вас чистое разделение, и ваш класс даже можно повторно использовать без Zend \ Config. Если у вас много вариантов конфигурации, вы можете создать отдельный класс конфигурации, расширяющий \Zend\StdLib\AbstractOptions
и \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.php
или Module.php
public function getServiceConfig() { return array('factories' => array( 'marketo_client' => 'Marketo\Service\ClientServiceFactory' ); }
Теперь пользователи могут получить ваш клиент из ServiceManager. Вся конфигурация настроена правильно.
$sm->get('marketo_client');