2012-09-17 25 views
16

Necesito obtener el adaptador del formulario, pero todavía no pude.Zend FrameWork 2 Obtener ServiceLocator en el formulario y completar una lista desplegable

En mi controlador que puedo recuperar el adaptador utilizando la siguiente:

// module/Users/src/Users/Controller/UsersController.php 
public function getUsersTable() 
{ 
    if (! $this->usersTable) { 
     $sm = $this->getServiceLocator(); 
     $this->usersTable = $sm->get('Users\Model\UsersTable'); 
    } 
    return $this->usersTable; 
} 

En mi módulo de E también lo hizo:

// module/Users/Module.php 
public function getServiceConfig() 
{ 
    return array(
      'factories' => array(
        'Users\Model\UsersTable' => function($sm) { 
         $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); 
         $uTable  = new UsersTable($dbAdapter); 
         return $uTable; 
        }, 
        //I need to get this to the list of groups 
        'Users\Model\GroupsTable' => function($sm) { 
         $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); 
         $gTable  = new GroupsTable($dbAdapter); 
         return $gTable; 
        }, 
      ), 
    ); 
} 

Podría alguien darme un ejemplo de cómo obtener el adaptador a la tabla de la forma de grupo?

He seguido este ejemplo para mis usuarios del formulario: http://framework.zend.com/manual/2.0/en/modules/zend.form.collections.html

editar desde aquí ...

Tal vez me he expresado mal para hacer la pregunta.

Lo que realmente tengo que hacer es completar una selección (desplegable) con información de mis grupos de tablas.

por eso es necesario para obtener los servicios dentro de mi clase formUsuario por ServiceLocatorAwareInterface (see this link) implementado porque por defecto, el Zend Framework MVC registra un inicializador que inyectará en la instancia ServiceLocatorAwareInterface ServiceManager La implementación de cualquier clase.

Después de recuperar los valores de los grupos de tablas y completar la selección.

El problema es que de todas las maneras que he probado, la getServiceLocator() devuelve la siguiente:

Call to a member function get() on a non-object in 
D:\WEBSERVER\htdocs\Zend2Control\module\Users\src\Users\Form\UsersForm.php 
on line 46 

justo lo que quería hacer esto en mi formulario de usuario ...

namespace Users\Form; 

use Zend\ServiceManager\ServiceLocatorAwareInterface; 
use Zend\ServiceManager\ServiceLocatorInterface; 
use Zend\Form\Element; 
use Zend\Form\Form; 

class UsersForm extends Form implements ServiceLocatorAwareInterface 
{ 

    protected $serviceLocator; 

    public function getServiceLocator() 
    { 
     return $this->serviceLocator; 
    } 

    public function setServiceLocator (ServiceLocatorInterface $serviceLocator) 
    { 
     $this->serviceLocator = $serviceLocator; 
    } 

    public function __construct ($name = null) 
    { 
     parent::__construct('users'); 

     $this->setAttribute('method', 'post');   

     $sm = $this->getServiceLocator(); 

     $groups = $sm->get('Users\Model\GroupsTable')->fetchAll(); // line 46  

     $select = new Element\Select('groups'); 

     $options = array(); 

     foreach ($groups as $group) { 

      $options[$group->id] = $group->name; 
     } 

     $select->setValueOptions($options); 

     $this->add($select); 

     // and more elements here... 
+2

Hola, ¿ha encontrado la solución para esto? –

Respuesta

1

En module.php creo dos servicios. Vea cómo alimentar el adaptador al formulario.

public function getServiceConfig() 
{ 
    return array(
     'factories' => array(
      'db_adapter' => function($sm) { 
       $config = $sm->get('Configuration'); 
       $dbAdapter = new \Zend\Db\Adapter\Adapter($config['db']); 
       return $dbAdapter; 
      }, 

      'my_amazing_form' => function ($sm) { 
       return new \dir\Form\SomeForm($sm->get('db_adapter')); 
      }, 

     ), 
    ); 
} 

En el código de formulario que utiliza que se alimentan a lo:

namespace ....\Form; 

use Zend\Form\Factory as FormFactory; 
use Zend\Form\Form; 

class SomeForm extends Form 
{ 

    public function __construct($adapter, $name = null) 
    { 
     parent::__construct($name); 
     $factory = new FormFactory(); 

     if (null === $name) { 
      $this->setName('whatever'); 
     } 

    } 
} 
+0

Edité mi pregunta. Creo que ahora es más claro de entender. Gracias por su respuesta. – JulianoMartins

+0

Para rellenar las opciones de selección simplemente pase el modelo (o cualquier otra clase/adaptador/lo que sea) al formulario mencionado en mi respuesta. Entonces podrás interactuar con él. – michaelbn

0

se realiza el tratamiento en el modelo, mediante la adición de un método que acepta una forma

public function buildFormSelectOptions($form, $context = null) 
{ 
    /** 
    * Do this this for each form element that needs options added 
    */ 
    $model = $this->getServiceManager()->get('modelProject'); 

    if (empty($context)){ 
     $optionRecords = $model->findAll(); 
    } else { 
     /** 
     * other logic for $optionRecords 
     */ 
    } 

    $options = array('value'=>'', 'label'=>'Choose a Project'); 
    foreach ($optionRecords as $option) { 
     $options[] = array('value'=>$option->getId(), 'label'=>$option->getName()); 
    } 

    $form->get('project')->setAttribute('options', $options); 
} 

Como la forma se pasa por referencia, podemos hacer algo como esto en el controlador donde se genera el formulario:

$builder = new AnnotationBuilder(); 
    $form = $builder->createForm($myEntity); 
    $myModel->buildFormSelectOptions($form, $myEntity); 

    $form->add(array(
     'name' => 'submitbutton', 
     'attributes' => array(
      'type' => 'submit', 
      'value' => 'Submit', 
      'id' => 'submitbutton', 
     ), 
    )); 

    $form->add(array(
     'name' => 'cancel', 
     'attributes' => array(
      'type' => 'submit', 
      'value' => 'Cancel', 
      'id' => 'cancel', 
     ), 
    )); 

Nota: El ejemplo asume que la forma base se crea mediante anotaciones, pero no importa cómo se crea la forma inicial.

6

Este es el método que utilicé para solucionar ese problema.

En primer lugar, desea hacer que su formulario implemente ServiceLocatorInterface como lo ha hecho.

A continuación, todavía tienen que inyectar manualmente el localizador de servicios, y como todo el formulario se genera en el interior del contrstuctor tendrá que inyectar a través del contructor demasiado (sin ideal para construir todo en el constructor sin embargo)

module.php

/** 
* Get the service Config 
* 
* @return array 
*/ 
public function getServiceConfig() 
{ 
    return array(
     'factories' => array(
      /** 
      * Inject ServiceLocator into our Form 
      */ 
      'MyModule\Form\MyForm' => function($sm) { 
       $form = new \MyModule\Form\MyFormForm('formname', $sm); 
       //$form->setServiceLocator($sm); 

       // Alternativly you can inject the adapter/gateway directly 
       // just add a setter on your form object... 
       //$form->setAdapter($sm->get('Users\Model\GroupsTable')); 

       return $form; 
      }, 
     ), 
    ); 
} 

Ahora dentro de su controlador que obtener su formulario como el siguiente:

// Service locator now injected 
$form = $this->getServiceLocator()->get('MyModule\Form\MyForm'); 

Ahora usted tendrá acceso a la fu ll servicio de localización dentro de la forma, de hacerse con cualquier otro servicio, etc., tales como:

$groups = $this->getServiceLocator()->get('Users\Model\GroupsTable')->fetchAll(); 
+1

Me gustó más esta respuesta, pero descubrí que guardar el localizador de servicios dentro del formulario es realmente una gran cantidad de memoria, así que en lugar de guardarlo dentro del formulario para mi caso, preferiría pasarlo en el constructor, usar todo lo que necesite del config y no guardarlo. – gmaliar

+0

Estoy allí contigo, es realmente molesto ... me alegra ver que Zend lo arregló muy bien. –

+0

Tener lo que es solo una referencia dentro de un objeto no es "pesado de memoria". – AsTeR

0

Un método alternativo para las otras respuestas sería la creación de un ServiceManager inicializador.

Un ejemplo de un inicializador existente es cómo se inyecta el ServiceManager si su instancia implementa ServiceLocatorAwareInterface.

La idea sería crear una interfaz que compruebe en su initialiser, esta interfaz puede parecer:

interface FormServiceAwareInterface 
{ 
    public function init(); 
    public function setServiceManager(ServiceManager $serviceManager); 
} 

Un ejemplo de lo que su inicializador puede verse como:

class FormInitializer implements InitializerInterface 
{ 
    public function initialize($instance, ServiceLocatorInterface $serviceLocator) 
    { 
     if (!$instance instanceof FormServiceAwareInterface) 
     { 
      return; 
     } 

     $instance->setServiceManager($serviceLocator); 
     $instance->init(); 
    } 
} 

Cualquier cosa que ocurra en init() tendría acceso al ServiceManager. Por supuesto, necesitaría agregar su inicializador a su configuración de SM.

No es perfecto, pero funciona bien para mis necesidades y también se puede aplicar a cualquier Fieldsets extraído del ServiceManager.

7

Las otras varias respuestas aquí generalmente son correctas, para ZF < 2.1.

Una vez que sale 2.1, el marco tiene una bonita nice solution. Esto formaliza más o menos la solución de DrBeza, es decir: usando un inicializador, y luego moviendo cualquier forma-bootstrapping en un método init() que se llama después de que todas las dependencias hayan sido inicializadas.

He estado jugando con la rama de desarrollo, funciona bastante bien.

0

Esta es la forma en que solía solucionar ese problema.

primer lugar, en module.php, crear el servicio (tal y como lo ha hecho):

// module/Users/Module.php 
public function getServiceConfig() 
{ 
    return array(
      'factories' => array(
        'Users\Model\UsersTable' => function($sm) { 
         $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); 
         $uTable  = new UsersTable($dbAdapter); 
         return $uTable; 
        }, 
        //I need to get this to the list of groups 
        'Users\Model\GroupsTable' => function($sm) { 
         $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); 
         $gTable  = new GroupsTable($dbAdapter); 
         return $gTable; 
        }, 
      ), 
    ); 
} 

Luego, en el controlador, tengo una referencia al servicio:

$users = $this->getServiceLocator()->get('Test\Model\TestGroupTable')->fetchAll(); 
     $options = array(); 
     foreach ($users as $user) 
      $options[$user->id] = $user->name; 
     //get the form element 
     $form->get('user_id')->setValueOptions($options); 

Y viola, ese trabajo.

Cuestiones relacionadas