Можно ли создавать переменные или даже общие объекты (например, адаптер БД) в модуле 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->.
Я ценю любое руководство! Благодаря!
Хорошо … многочастный ответ.
Это было легко, как только я увидел, что это работает. Но это зависит от предварительной обработки ниже. В корне вашего приложения отбросьте файл в 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 решена для меня!
Моя другая проблема заключалась в том, что я мог получить доступ к некоторым объектам и / или значениям на глобальном уровне и загрузить их при инициализации контроллера и действий. Насколько я понимаю, его невозможно получить в конфигураторе диспетчера служб в __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 решена! Инициализация для контроллеров.
Хорошо, последнее, что я хотел, – это доступ к моему 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.