El módulo Zend Framework 2 comparte variables entre los controladores en Bootstrap

¿Es posible crear variables o incluso objetos compartidos (como el adaptador DB) en Module.php para usar en todos los controladores de vista? (Zend Framework 2)

Por ejemplo:

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

Y en un controlador, de alguna manera accede usando:

 $this->moduleConfig['db'] 

En lo que antecede, sé que sería simplemente la matriz de configuración para el adaptador de db, pero ¿cómo funcionaría eso?

Veo que uno puede hacer esto en una acción de controlador:

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

No quiero hacer eso en todos los lugares donde necesito mi configuración. ¿Cómo podría hacer algo así como: $ this-> config ?? Entonces está disponible para todas las acciones. Mejor aún, ¿cómo hacer eso en todo el Módulo? Sé que estoy haciendo todo mal, pero en ZF1 teníamos Zend_Registry :: get () para cosas simples como esta. Estoy leyendo los documentos y todo tipo de tuts, pero siempre se hacen suposiciones y me pierdo. Entonces, todo lo que realmente quiero es: A) Un elemento de configuración accesible a nivel mundial, B) Un adaptador de acceso universal accesible

Solo quiero llamar $ this-> db o $ this-> config-> item en mis controladores. es posible? Sé que me estoy perdiendo algo totalmente simple.

También intenté configurar $ this-> config en mi __construct usando $ this-> getServiceLocator () -> get (‘Config’); Pero entiendo que el localizador de servicios aún no está disponible durante la construcción. Intenté hacer lo mismo configurando un preDispatch en el onBootstrap del módulo, pero parece que no puedo obtener esos elementos en mis controladores.

Para tu información, tengo esto en mi global.php (y no, no se queda allí, solo ejemplo):

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

Puedo acceder a ese y a otros elementos en cualquier acción usando getServiceLocator (). Me gustaría que esos elementos estén disponibles como mis propiedades de controlador como en $ this-> config-> item.

¡Agradezco cualquier orientación! ¡Gracias!

Bien … respuesta multiparte.

1. Agregar variables de configuración, en todo el sitio. (y cómo acceder en los controladores)

Esto fue fácil, una vez que lo vi funcionar. Pero depende del preDispatch a continuación. En la raíz de su aplicación, coloque un archivo en config / autoload. Llámalo: things.config.local.php

En este archivo, simplemente devolvemos una matriz con elementos de configuración.

  array( 'avalue' => 'avalue1', 'boolvalue' => true, ), ); 

Entonces quiero acceso a eso en mi controlador. Suponiendo que crea una propiedad de configuración en el controlador, puede acceder de esta manera. (configura esa propiedad en preDispatch a continuación para que funcione) En mi sistema, preferiría recuperar ese valor de la siguiente manera:

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

Sin embargo, puedes invocarlo en una acción como esta:

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

Eso fue fácil en realidad. No estoy seguro de cómo hacer eso con un archivo ini, pero en mi caso no es necesario y mis archivos ini no son un gran problema para moverlos directamente a las matrices. ¡Problema 1 resuelto para mí!

2. Cómo obtener preDispatch en los controladores (porque __construct no cargará la configuración)

Mi otro problema era que podía obtener acceso a algunos objetos y / o valores a nivel global Y hacerlos cargar cuando el controlador y las acciones se inicializan. Según lo entiendo, no es posible acceder a la configuración del administrador de servicios en __construcción del controlador.

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

Lo anterior no funcionará. Creo que porque ServiceManager aún no está disponible durante la construcción de la clase de controlador. tiene sentido.

Un par de pasos adicionales, y puedo hacer que preDispatch funcione, similar a ZF1. ENTONCES las cosas de configuración funcionan. Así como el acceso a objetos globales, como la base de datos.

En el controlador, agregue el siguiente método:

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

Luego agrega los métodos pre y 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 } 

¡Problema 2 resuelto! Init para controladores.

3. Cómo usar lo anterior con ServiceManager para cargar un objeto DB para usar en Controller

De acuerdo, lo último que quería era acceder a mi db a nivel mundial. Y lo quería todo el controlador, así que puedo llamar $ this-> db-> fetchAll anywhere.

Primer administrador de servicios de configuración en global.php.
Además, tenga en cuenta que no lo voy a dejar exactamente así ya que está en mi archivo global.php. Pero funciona por ahora. Agregue estas matrices a la matriz de retorno en 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; }, ), ), 

En lo anterior, configuré la configuración db, luego service_manager tiene algunas fábricas, que están disponibles cuando es necesario en el rest de la aplicación. En mi caso, quería cierta comodidad para la compatibilidad con versiones anteriores de algunos de mis viejos códigos ZF1, así que agregué un módulo personalizado llamado FBDb. Encontré una fantástica clase wrapper / bridge-to-zf1-style-db llamada ZFBridge por Fabrizio Balliano. Funcionó muy bien para mis necesidades, puede encontrarlo aquí: https://github.com/fballiano/zfbridge

Tomé eso, lo modifiqué un poco, e hice un módulo. Entonces, el objeto FBDb está disponible en mis controladores como mi conexión a la base de datos. Lo mismo con “db-adapter” si quisiera utilizarlo en otro lugar.

De todos modos, en mi controlador, configuro “protected $ db”; al comienzo de la clase, así que tengo esa propiedad disponible. Entonces, como se muestra en el n. ° 2 anterior, he preDispatch asignando el objeto de la base de datos FBDb a $ this-> db.

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

Luego, en mis métodos de acción, si quiero, puedo llamar un conjunto de registros o un valor de db con esto:

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

O, para una matriz devuelta:

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

(Agregué fetchResults a ZFBridge para devolver solo el objeto PDO \ Results a partir de la consulta db para su uso en foreach más adelante).

Sé que algo de esto es, probablemente, un mal diseño o un “mal OOP”, pero funciona para mí y me gusta. Personalmente no uso entidades de datos basadas en objetos puros para todo, solo algunas cosas. Gran parte del tiempo, solo quiero dejar caer un conjunto de resultados y terminarlo. 🙂

Problemas resueltos Por ahora. Hace que ZF2 sea mucho más amigable ahora, si estás acostumbrado a ZF1.