处理Zend Framework中的依赖关系2表格

问题描述:

我想在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

所以我得到了这个工作与一些小的改变:

正如你提到的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