Zend Framework 2 разделяет переменные между контроллерами onBootstrap

Можно ли создавать переменные или даже общие объекты (например, адаптер БД) в модуле Module.php для использования во всех контроллерах представлений? (Zend Framework 2)

Например:

class Module { public function onBootstrap(MvcEvent $e) { $moduleConfig = $e->getServiceManager()->get('Config') } } 

И в контроллере, как-то доступ с помощью:

 $this->moduleConfig['db'] 

В приведенном выше я знаю, что это будет просто конфигурационный массив для адаптера db, но как это работает?

Я вижу, что это можно сделать в результате действия контроллера:

 $config = $this->getServiceLocator()->get('Config') $dba = new DbAdapter($config['db']); 

Я не хочу делать это в любом месте, где мне нужен мой конфиг. Как я могу сделать что-то вроде: $ this-> config ?? Таким образом, он доступен для всех действий. Еще лучше, как это сделать во всем модуле? Я знаю, что все происходит неправильно, но в ZF1 у нас был Zend_Registry :: get () для простых вещей, подобных этому. Я читаю документы и всевозможные мелочи, но всегда есть некоторые предположения, и я просто теряюсь. Так что все, что я действительно хочу, это: A) Доступный для всего мира элемент конфигурации, B) Доступный глобально доступный адаптер db

Я просто хочу вызвать элемент $ this-> db или $ this-> config-> в моих контроллерах. Это возможно? Я знаю, что мне не хватает чего-то совершенно простого.

Также я попытался установить $ this-> config в моем __construct, используя $ this-> getServiceLocator () -> get ('Config'); Но я понимаю, что во время построения показывается, что локатор сервисов еще не доступен. Я попытался сделать подобное, настроив preDispatch в onBootstrap модуля, но я не могу получить эти элементы в своих контроллерах.

FYI, у меня это есть в моем global.php (и нет, его не осталось, просто пример):

 'db' => array( 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=mydb;host=localhost;', 'username' => 'root', 'password' => '', 'driver_options' => array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ), ), 

Я могу получить доступ к этому и другим элементам при любых действиях с помощью getServiceLocator (). Я хотел бы, чтобы эти элементы были доступны в качестве свойств моего контроллера, как в элементе $ this-> config->.

Я ценю любое руководство! Благодаря!

Хорошо … многочастный ответ.

1. Добавление переменных конфигурации на весь сайт. (и как получить доступ к контроллерам)

Это было легко, как только я увидел, что это работает. Но это зависит от предварительной обработки ниже. В корне вашего приложения отбросьте файл в config / autoload. Назовите это: things.config.local.php

В этом файле мы просто возвращаем массив с элементами конфигурации.

 <?php return array( 'things' => array( 'avalue' => 'avalue1', 'boolvalue' => true, ), ); 

Поэтому я хочу получить доступ к этому в своем контроллере. Предполагая, что вы создаете свойство config в контроллере, вы можете получить к нему доступ таким образом. (вы устанавливаете это свойство в preDispatch ниже для его работы). В моей системе я бы предпочел получить это значение следующим образом:

 $this->config['things']['boolvalue']; 

Однако вы можете просто вызвать его в таком действии:

 $config = $this->getServiceLocator()->get('Config'); echo $config['things']['boolvalue']; 

На самом деле это было легко. Не уверен, как это сделать с ini-файлом, но в моем случае его не нужно, и мои ini-файлы не очень важны для непосредственного перемещения в массивы. Задача 1 решена для меня!

2. Как получить preDispatch в контроллерах (поскольку __construct не загружает конфигурацию)

Моя другая проблема заключалась в том, что я мог получить доступ к некоторым объектам и / или значениям на глобальном уровне и загрузить их при инициализации контроллера и действий. Насколько я понимаю, его невозможно получить в конфигураторе диспетчера служб в __construct контроллера.

 $this->getServiceLocator()->get('Config'); 

Вышеуказанное не будет работать. Я считаю, что ServiceManager еще не доступен во время построения класса контроллера. имеет смысл.

Пара дополнительных шагов, хотя, и я могу заставить preDispatch работать, подобно ZF1. ТОГДА работает конфиг. А также доступ к глобальным объектам, таким как база данных.

В контроллере добавьте следующий метод:

 protected function attachDefaultListeners() { parent::attachDefaultListeners(); $events = $this->getEventManager(); $this->events->attach('dispatch', array($this, 'preDispatch'), 100); $this->events->attach('dispatch', array($this, 'postDispatch'), -100); } 

Затем добавьте методы pre и post.

 public function preDispatch (MvcEvent $e) { // this is a db convenience class I setup in global.php // under the service_manager factories (will show below) $this->db = $this->getServiceLocator()->get('FBDb'); // this is just standard config loaded from ServiceManager // set your property in your class for $config (protected $config;) // then have access in entire controller $this->config = $this->getServiceLocator()->get('Config'); // this comes from the things.config.local.php file echo "things boolvalue: " . $this->config['things']['boolvalue']; } public function postDispatch (MvcEvent $e) { // Called after actions } 

Проблема 2 решена! Инициализация для контроллеров.

3. Как использовать вышеприведенное с ServiceManager для загрузки объекта базы данных для использования в контроллере

Хорошо, последнее, что я хотел, – это доступ к моему db по всему миру. И я хотел, чтобы это был контроллер, поэтому я могу назвать $ this-> db-> fetchAll в любом месте.

Первый менеджер службы установки в global.php.
Кроме того, имейте в виду, я не буду оставлять его точно так, как это происходит в моем файле global.php. Но сейчас это работает. Добавьте эти массивы в возвращаемый массив в global.php:

 'db' => array( 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=mydb;host=localhost;', 'username' => 'root', 'password' => '', 'driver_options' => array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ), ), 'service_manager' => array( 'factories' => array( 'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory', 'db-adapter' => function($sm) { $config = $sm->get('config'); $config = $config['db']; $dbAdapter = new Zend\Db\Adapter\Adapter($config); return $dbAdapter; }, 'FBDb' => function($sm) { $dba= $sm->get('db-adapter'); $db = new FBDb\Db($dba); return $db; }, ), ), 

В приведенном выше, я настраиваю конфигурацию db, затем у service_manager есть некоторые фабрики, которые становятся доступными, когда это необходимо в остальном приложении. В моем случае, я хотел немного удобства для обратной совместимости с некоторыми из моего старого кода ZF1, поэтому я добавил настраиваемый модуль под названием FBDb. Я нашел фантастический класс обертки / моста к zf1-style-db под названием ZFBridge от Fabrizio Balliano. Работал отлично для моих нужд, вы можете найти здесь: https://github.com/fballiano/zfbridge

Я взял это, немного изменил его и создал модуль. Таким образом, объект FBDb доступен в моих контроллерах в качестве моего подключения к базе данных. То же самое с «db-adapter», если я захочу использовать его в другом месте.

Во всяком случае, в моем контроллере я настраиваю «protected $ db;» в начале класса, поэтому у меня есть это свойство. Затем, как показано в № 2 выше, у меня есть preDispatch, назначающая объект базы данных FBDb $ this-> db.

 $this->db = $this->getServiceLocator()->get('FBDb'); 

Затем в моих методах действий, если я хочу, я могу вызвать набор записей или значение db следующим образом:

 $sql = 'select * from customer where cust_nbr between ? and ?'; $rs = $this->db->fetchResults($sql, array('120400', '125250')); 

ИЛИ, для возвращаемого массива:

 $rs = $this->db->fetchAll($sql, array('120400', '125250')); 

(Я добавил fetchResults в ZFBridge, чтобы вернуть только объект PDO \ Results из запроса db для использования в foreach позже.)

Я знаю, что некоторые из них – плохой дизайн или «плохой ООП», но он работает для меня, и мне это нравится. Я лично не использую чистые объекты данных, основанные на объектах, для всего, только некоторые вещи. В большинстве случаев я просто хочу сбросить набор результатов и сделать это. 🙂

Проблемы решены. На данный момент. Теперь ZF2 становится более дружелюбным, если вы привыкли к ZF1.