2012-09-17 11 views
16

ho bisogno di ottenere l'adattatore dalla forma verso il basso, ma ancora non poteva.Zend Framework 2 Get ServiceLocator nella forma e compilare un elenco a discesa

Nel mio controller posso recuperare l'adattatore utilizzando il seguente:

// 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; 
} 

Nel mio modulo ho fatto così:

// 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; 
        }, 
      ), 
    ); 
} 

Qualcuno potrebbe darmi un esempio di come raggiungere l'adattatore al tabella dal modulo di gruppo?

Ho seguito questo esempio per i miei utenti di forma: http://framework.zend.com/manual/2.0/en/modules/zend.form.collections.html

CURA da qui ...

Forse mi sono espresso male per fare la domanda.

Quello che devo veramente fare è compilare una selezione (Discesa verso il basso) con le informazioni dai miei gruppi di tabelle.

Così ho bisogno di ottenere i servizi all'interno della mia classe form da ServiceLocatorAwareInterface (see this link) implementata perché per impostazione predefinita, la Zend Framework MVC registra un inizializzatore che inietterà nel ServiceManager istanza ServiceLocatorAwareInterface implementazione di qualsiasi classe.

Dopo aver recuperato i valori dai gruppi di tabelle e compilato la selezione.

Il problema è che di tutti i modi che ho provato, il getServiceLocator() restituisce questo:

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 

Volevo solo fare questo nel mio form ...

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

hi hai trovato la soluzione per questo? –

risposta

1

In module.php creo due servizi. Guarda come applico l'adattatore al modulo.

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')); 
      }, 

     ), 
    ); 
} 

Nel codice del modulo che io uso di alimentazione a tutto ciò:

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

Ho modificato la mia domanda. Credo che ora sia più chiaro da capire. Grazie per la tua risposta. – JulianoMartins

+0

Per popolare le opzioni di selezione basta passare il modello (o qualsiasi altra classe/adattatore/qualunque) al modulo come indicato nella mia risposta. Allora sarai in grado di interagire con esso. – michaelbn

0

gestiamo questo nel modello, con l'aggiunta di un metodo che accetta un modulo

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); 
} 

Come la forma viene passato per riferimento, possiamo fare qualcosa di simile nel controller in cui è compilato il modulo:

$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: l'esempio presuppone che il modulo di base sia compilato tramite annotazioni, ma non importa come si crea il modulo iniziale.

6

questo è il metodo che ho usato per aggirare questo problema.

In primo luogo, si desidera implementare ServiceLocatorInterface come si è fatto.

Sarà quindi ancora bisogno di iniettare manualmente il localizzatore di servizio, e come l'intero modulo viene generato all'interno del contrstuctor è necessario iniettare attraverso il contructor troppo (non ideale per costruire il tutto nel costruttore però)

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; 
      }, 
     ), 
    ); 
} 

Ora dentro il controller si ottiene il modulo come questo:

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

Ora si avrà accesso al fu ll servizio di localizzatore all'interno del modulo, per entrare in possesso di tutti gli altri servizi, ecc, quali:

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

Questa risposta mi è piaciuta di più, ma ho scoperto che il salvataggio del localizzatore di servizio all'interno del modulo è davvero pesante, quindi invece di salvarlo nel modulo per il mio caso, preferirei passarlo nel costruttore, utilizzare tutto ciò di cui ho bisogno dal config e non salvarlo. – gmaliar

+0

Sono proprio qui con te, è davvero fastidioso ... felice di vedere che Zend ha sistemato bene. –

+0

Avere quello che è solo un riferimento all'interno di un oggetto non è "pesante nella memoria". – AsTeR

0

Un metodo alternativo alle altre risposte sarebbe quello di creare un ServiceManager Initializer.

Un esempio di un inizializzatore esistente è il modo in cui il ServiceManager viene iniettato se l'istanza implementa ServiceLocatorAwareInterface.

L'idea sarebbe quella di creare un'interfaccia che si controlla nel vostro initialiser, questa interfaccia può sembrare:

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

Un esempio di ciò che il vostro Initializer può apparire come:

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

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

Tutto ciò che accade in init() avrebbe accesso allo ServiceManager. Naturalmente è necessario aggiungere il proprio inizializzatore alla configurazione SM.

Non è perfetto ma funziona perfettamente per le mie esigenze e può anche essere applicato a qualsiasi Fieldset estratto dal ServiceManager.

7

Le altre varie risposte qui in genere corrette, per ZF < 2.1.

Una volta che 2.1 è fuori, il framework ha un bel nice solution. Questo più o meno formalizza la soluzione di DrBeza, vale a dire: usando un inizializzatore, e poi spostando qualsiasi forma - bootstrap in un metodo init() che viene chiamato dopo che tutte le dipendenze sono state inizializzate.

Ho giocato con il ramo di sviluppo, funziona abbastanza bene.

0

Questo è il modo in cui ho usato aggirare questo problema.

primo luogo, in Module.php, creare il servizio (proprio come avete fatto):

// 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; 
        }, 
      ), 
    ); 
} 

Poi nel controller, ho ottenuto un riferimento al servizio:

$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); 

E viola, funziona.

Problemi correlati