2012-09-17 16 views
16

我需要從窗體中獲取適配器,但仍不能。Zend FrameWork 2在窗體中獲取ServiceLocator並填充下拉列表

在我的控制,我可以使用恢復適配器如下:

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

在我的模塊我這樣做:

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

可能有人給我一個例子,如何獲取適配器的表格中的表格?

我按照這個例子,我的表單的用戶: http://framework.zend.com/manual/2.0/en/modules/zend.form.collections.html

來自此編輯...

也許是我表達自己錯了要問的問題。

我真正需要做的是用我的表組中的信息填充select(Drop Down)。

所以我需要通過ServiceLocatorAwareInterface(see this link)實現,因爲默認情況下,讓我的用戶窗體類中的服務,Zend Framework的MVC註冊一個初始化這將注入的ServiceManager實例ServiceLocatorAwareInterface實現任何類。

檢索表組中的值並填充選擇。

的問題是,我已經嘗試了所有的方法,該getServiceLocator()返回此:

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 

我只想做這在我的窗體...

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

你好你是否找到了解決方案? –

回答

1

在module.php中我創建了兩個服務。瞭解我如何將適配器提供給表單。

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

     ), 
    ); 
} 

在表單代碼中,我使用飼料到任何:

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

我編輯了我的問題。我相信現在更清楚地瞭解。感謝您的回覆。 – JulianoMartins

+0

要填充選擇選項,只需將模型(或任何其他類/適配器/任何)傳遞給我的答案中提到的窗體。然後你將能夠與它進行交互。 – michaelbn

0

我們處理這個模型中,通過添加接受的形式

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

隨着形式的方法通過引用傳遞,我們可以在構建表單的控制器中執行類似操作:

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

注意:該示例假定基礎表單是通過註釋構建的,但不管您如何創建初始表單。

6

這是我用來解決這個問題的方法。

首先,您希望使您的表單像您所做的那樣實現ServiceLocatorInterface。

然後,您將仍然需要手動進服務定位器,並作爲contrstuctor內產生的全部表,您需要通過構造器太(沒有理想的建造這一切在構造雖然)

注入

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

現在你的控制器中您得到您的形式是這樣的:

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

現在你將有機會獲得福以獲得任何其他服務等,例如:

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

我最喜歡這個答案,但我發現在窗體內保存服務定位器真的是內存沉重,所以不是將它保存在我的情況下的表單中,而是將它傳遞給構造函數,使用我需要的任何東西配置並不保存它。 – gmaliar

+0

我和你在一起,這真的很煩人......很高興看到Zend很好地修復了它。 –

+0

具有什麼只是對象內的引用不是「內存沉重」。 – AsTeR

0

其他答案的另一種方法是創建一個ServiceManager初始化程序。

現有初始化程序的一個示例是,如果您的實例實現ServiceLocatorAwareInterface,ServiceManager將如何被注入。

的想法是創建您在初始化器檢查的接口,這個接口可能看起來像:

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

你的初始化器可以是什麼樣子的一個例子:

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

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

發生在init()中的任何情況都可以訪問ServiceManager。當然,你需要將你的初始化器添加到你的SM配置中。

它並不完美,但它對我的需求很好,也可以應用於從ServiceManager中提取的任何字段集。

7

這裏的其他各種答案一般正確,對於ZF < 2.1。

一旦2.1結束,該框架有一個漂亮的nice solution。這或多或少形式化了DrBeza的解決方案,即:使用初始化器,然後將任何形式自舉移動到初始化所有依賴項後調用的init()方法中。

我一直在玩開發分支,它工作得很好。

0

這是我用來解決這個問題的方式。

首先,在Module.php,創建服務(就像你這樣做):在控制器

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

然後,我到了服務的參考:

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

而且中提琴,那個工作。