2013-03-16 84 views
4

我想在ZF2中構建一個表單。當我想從數據庫表中填充選擇輸入元素的選項數組時,問題就出現了。 @timdev對這個問題的迴應Zend FrameWork 2 Get ServiceLocator In Form and populate a drop down list指出了ZF2文檔描述'正確'方法的地方。我仔細地跟蹤了這一點,但我懷疑他們必須留下明顯的代碼,假設我能填補空白,因爲我無法實現它。任何人都可以看到我做錯了什麼?處理Zend Framework中的依賴關係2表格

我開始用一種形式,而我添加一個字段:

namespace Ctmm\Form; 
use Zend\Form\Form; 

class AddPropertyForm extends Form { 

public function __construct() { 

    parent::__construct('AddProperty'); 

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

    $this->add(array(
     'name' => 'property', 
     'type' => 'PropertyFieldset' 
    )); 

} }

我然後創建字段集:

namespace Ctmm\Form; 
use Ctmm\Model; 
use Zend\Form\Fieldset; 

class PropertyFieldset extends Fieldset { 

public function __construct(PropertyType $property_type) { 
    $this->add(array(
     'name' => 'property_type', 
     'type' => 'Zend\Form\Element\Select', 
     'attributes' => array(
      'required' => true, 
     ), 
     'options' => array(
      'label' => 'Property Type', 
      'value_options' => array(
       0 => 'Detached house', 
       1 => 'Semi-detached house', 
       2 => 'Terraced house', 
       3 => 'Bungalow', 
       4 => 'Maisonette', 
       5 => 'Flat', 
       6 => 'Land', 
       7 => 'Development Opportunity', 
      ), 
     ), 
    )); 

} 

}

正如你可以看到我注入PropertyType依賴到字段集。在這個階段,我甚至沒有用它來生成選項數組。我硬編碼數組值以避免添加可能的錯誤的另一個來源。一旦我得到表單渲染,然後我會嘗試從PropertyType表中拉出數組數據。

現在我成立了我的Module.php表單元素經理:}

namespace Ctmm; 
use Ctmm\Form\PropertyFieldset; 
use Zend\ModuleManager\Feature\FormElementProviderInterface; 

class Module implements FormElementProviderInterface { 

public function getFormElementConfig() { 
    return array(
     'factories' => array(
      'PropertyFieldset' => function($sm) { 
       $serviceLocator = $sm->getServiceLocator(); 
       $property_type = $serviceLocator->get('Ctmm\Model\PropertyType'); 
       $fieldset = new PropertyFieldset($property_type); 
      } 
     ) 
    ); 
} 

這段代碼是直接從文檔。我已經嘗試添加

return $fieldset; 

到PropertyFieldset工廠,我甚至嘗試添加

'invokables' => array(
'PropertyFieldset' => 'Ctmm\Form\PropertyFieldset' 
) 

到getFormElementConfig陣列,以及與可調用替換工廠。

最後一步是使用表單元素管理器來創建我的控制器操作形式:

public function addAction() {   
$formManager = $this->serviceLocator->get('FormElementManager'); 
    $form  = $formManager->get('Ctmm\Form\AddPropertyForm'); 
} 

無論我做什麼,我得到一個錯誤稱的ServiceManager無法創建PropertyFieldset:

的Zend \的ServiceManager \異常\ ServiceNotFoundException的

文件:

/home/mike/public_html/ctmm/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:456 

消息:

Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for PropertyFieldset 

堆棧跟蹤:

#0 /home/mike/public_html/ctmm/vendor/zendframework/zendframework/library/Zend/ServiceManager/AbstractPluginManager.php(103): Zend\ServiceManager\ServiceManager->get('PropertyFieldse...', true) 
#1 /home/mike/public_html/ctmm/vendor/zendframework/zendframework/library/Zend/Form/Factory.php(110): Zend\ServiceManager\AbstractPluginManager->get('PropertyFieldse...') 
#2 /home/mike/public_html/ctmm/vendor/zendframework/zendframework/library/Zend/Form/Form.php(145): Zend\Form\Factory->create(Array) 
#3 /home/mike/public_html/ctmm/module/Ctmm/src/Ctmm/Form/AddPropertyForm.php(33): Zend\Form\Form->add(Array) 

33號線在AddPropertyForm.php是我嘗試添加自己的自定義PropertyFieldset。很明顯,我在字段集本身或我聲明的方式中有一個錯誤。我嘗試過不注入PropertyType依賴項,但這沒有什麼區別。爲了完整起見,我的屬性類型模型的代碼是:

namespace Ctmm\Model; 

class PropertyType { 
public $id; 
public $property_type; 
protected $adapter; 

public function __construct($adapter) { 
    $this->adapter = $adapter; 
} 

public function exchangeArray($data) { 
    $this->id = (isset($data['id'])) ? $data['id'] : null; 
    $this->property_type = (isset($data['property_type'])) ? $data['property_type'] : null; 
} 

public function getPropertyType() { 
    return $this->property_type; 
} 

public function fetchAll() { 

    $sql_query = "SELECT id, property_type from property_type"; 
    $statement = $this->adapter->createStatement($sql_query); 
    $results = $statement->execute(); 
    return $results; 
} 

}

編輯:

我沒有一個答案,但我做了一些更多的研究。我直接在控制器中創建了一個fieldset來測試我的PropertyFieldset類和它的依賴模型。

$property_type = $this->getServiceLocator()->get('Ctmm\Model\PropertyType'); 
$fieldset = new PropertyFieldset($property_type); 

這沒有立即起作用。首先,我不得不採取暗示出字段集構造器

public function __construct(PropertyFieldset $property_type) { 

成了

public function __construct($property_type) { 

然後我不得不添加

parent::__construct('propertyfieldset'); 

之前,將允許我補充的元素。

有一次,我添加了這些變化,我能夠在控制器中創建一個PropertyFieldset對象。我可以通過var_dump()來測試它。

不幸的是,這些更改PropertyFieldset類沒有解決根本問題,所以,當我嘗試創建控制器的形式,它會產生相同的錯誤了。我有,至少免除了PropertyFieldset類和它的依賴模型,它告訴我,我的Module.php類中的getFormElementConfig()有錯誤

+0

什麼是您的AddPropertyForm工廠是什麼樣子?至於類型暗示。我認爲你需要使用完整的命名空間,所以:使用Ctmm \ Model \ PropertyType;或將完整路徑放在構造函數中 – 2013-03-16 16:26:19

+0

我不使用工廠來創建AddPropertyForm。該窗體使用新的FormElementManager在控制器中創建。該文檔堅持使用它來創建表單,以便它獲取getFormElementConfig()中定義的元素。 – 2013-03-16 16:33:27

+0

只是有一個混亂與它,我認爲如果你改變__construct方法init在AddPropertyForm它應該工作。您還需要從工廠返回現場組。我會仔細檢查一下併發布答案。 – 2013-03-16 17:39:31

回答

6

所以我得到了這個工作與一些小的改變:

正如你提到的PropertyFieldSet應該叫父母建造像這樣:

parent::__construct('propertyfieldset'); 

ElementConfig應該像這樣:

public function getFormElementConfig() { 
    return array(
     'factories' => array(
      'PropertyFieldset' => function($sm) { 
       $serviceLocator = $sm->getServiceLocator(); 
       $property_type = $serviceLocator->get('Ctmm\Model\PropertyType'); 
       $fieldset = new PropertyFieldset($property_type); 
       return $fieldset; 
      }, 
     ) 
    ); 
} 

而AddPropertyForm應該像這樣:

namespace Ctmm\Form; 
use Zend\Form\Form; 

class AddPropertyForm extends Form { 

    public function init() { 

     parent::__construct('AddProperty'); 

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

     $this->add(array(
      'name' => 'addproperty', 
      'type' => 'PropertyFieldset', 
     )); 
    } 
} 

而不是使用__construct我們使用的init()。這個函數顯然是在工廠實例化時調用的:http://framework.zend.com/apidoc/2.1/classes/Zend.Form.Form.html#init

關於構建select,我將TableGateway對象傳遞給fieldSet而不是模型。然後用使用fetchall功能,我們可以做的形式如下:

class PropertyFieldset extends Fieldset { 

    public function __construct(PropertyTypeTable $propertyTypeTable) { 
     parent::__construct('propertyfieldset'); 


     $propertyValOpts = array(); 
     foreach($propertyTypeTable->fetchAll() as $propertyRow) { 
      array_push($propertyValOpts,$propertyRow->property_type); 
     } 

     $this->add(array(
      'name' => 'property_type', 
      'type' => 'Zend\Form\Element\Select', 
      'attributes' => array(
       'required' => true, 
      ), 
      'options' => array(
       'label' => 'Property Type', 
       'value_options' => $propertyValOpts 
      ), 
     )); 
    } 
} 

希望這有助於:)

+0

感謝您的幫助艾登,我真的很感激。如果我能爲額外的TableGateway建議額外提供+1,我會。 – 2013-03-16 18:47:09

+0

我想這個代碼,工廠工作,如果我做了他們的var_dump他們看起來確定。但我無法讓它顯示在窗體上。它只給我空白的文本字段。任何線索都可能是錯誤的? – Rickard 2013-06-29 20:06:57