4

我正在尝试在 ZF2 中构建一个表单。当我想从数据库表中填充 Select 输入元素的选项数组时,问题就出现了。对此问题的回应Zend FrameWork 2 Get ServiceLocator In Form and populate a drop down list by @timdev 向我指出了描述“正确”方法的 ZF2 文档。我仔细地遵循了这一点,但我怀疑他们一定遗漏了明显的代码,假设我可以填补空白,因为我无法让它工作。谁能看到我做错了什么?

我从添加字段集的表单开始:

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\Exception\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)

AddPropertyForm.php 中的第 33 行是我尝试添加自定义 PropertyFieldset 的地方。显然,我在字段集本身或我声明它的方式上有一个错误。我尝试过不注入 PropertyType 依赖项,但这没有什么区别。为了完整起见,我的 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;
}

}

编辑:

我没有答案,但我做了更多调查。我直接在控制器中创建了一个字段集来测试我的 PropertyFieldset 类及其依赖模型。

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

这并没有立即奏效。首先,我必须从 Fieldset 构造器中获取提示

public function __construct(PropertyFieldset $property_type) {

变成了

public function __construct($property_type) {

然后我不得不添加

parent::__construct('propertyfieldset');

在它允许我添加一个元素之前。

一旦我添加了这些更改,我就可以在控制器中创建一个 PropertyFieldset 对象。我可以通过 var_dump() 对其进行测试。

不幸的是,对 PropertyFieldset 类的这些更改并没有解决基本问题,因此当我尝试在控制器中创建表单时,它会产生与以前相同的错误。我至少免除了 PropertyFieldset 类及其依赖模型,这对我说我的 Module.php 类中的 getFormElementConfig() 有问题

4

1 回答 1

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

关于构建选择,我会将 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
            ),
        ));
    }
}

希望这可以帮助 :)

于 2013-03-16T18:09:08.003 回答