ZF2 形式和原则 2 修改了value_options


ZF2 Form and Doctrine 2 modify the value_options

我在我的Zend Framework 2项目中使用了Doctrine 2。现在,我已经创建了一个表单,并使用数据库中的值创建了一个下拉列表。我现在的问题是我想更改使用哪些值,而不是从存储库中返回的值。好的,这里有一些代码可以更好地理解:

$this->add(
            array(
                    'type' => 'DoctrineModule'Form'Element'ObjectSelect',
                    'name' => 'county',
                    'options' => array(
                            'object_manager' => $this->getObjectManager(),
                            'label' => 'County',
                            'target_class'   => 'Advert'Entity'Geolocation',
                            'property'       => 'county',
                            'is_method' => true,
                            'empty_option' => '--- select county ---',
                            'value_options'=> function($targetEntity) {
                                $values = array($targetEntity->getCounty() => $targetEntity->getCounty());
                                return $values;
                            },
                            'find_method'        => array(
                                    'name'   => 'getCounties',
                            ),
                    ),
                    'allow_empty'  => true,
                    'required'     => false,
                    'attributes' => array(
                            'id' => 'county',
                            'multiple' => false,
                    )
            )
    ); 

我想将我的选择的值设置为县名称,而不是 ID。我以为我需要需要数组的"value_options"。我像上面一样尝试过,但得到了

错误消息:传递给 Zend''Form''Element''Select::setValueOptions(( 的参数 1 必须是给定的数组类型,对象

这可能吗?

我打算修改你的代码,尽管在检查了ObjectSelect代码后,我很惊讶(据我所知(如果不扩展类,这实际上是不可能的。这是因为该值始终是从 id 生成的。

我使用工厂(不带ObjectSelect(创建所有表单元素,尤其是需要不同列表的复杂元素。

替代解决方案

首先在存储库中创建一个返回正确数组的新方法。这将允许您在其他任何地方需要它时重用相同的方法(不仅仅是表单!

class FooRepository extends Repository
{
    public function getCounties()
    {
        // normal method unchanged, returns a collection
        // of counties
    }
    public function getCountiesAsArrayKeyedByCountyName()
    {
        $counties = array();
        foreach($this->getCounties() as $county) {
            $counties[$county->getName()] = $county->getName();
        }
        return $counties;
    }
}

接下来,创建一个自定义选择工厂,该工厂将为您设置值选项。

namespace MyModule'Form'Element;
use Zend'Form'Element'Select;
use Zend'ServiceManager'ServiceLocatorInterface;
use Zend'ServiceManager'FactoryInterface;
class CountiesByNameSelectFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $formElementManager)
    {
        $element = new Select;
        $element->setValueOptions($this->loadValueOptions($formElementManager));
        // set other select options etc
        $element->setName('foo')
                ->setOptions(array('foo' => 'bar'));
        return $element;
    }
    protected function loadValueOptions(ServiceLocatorInterface $formElementManager)
    {
        $serviceManager = $formElementManager->getServiceLocator();
        $repository = $serviceManager->get('DoctrineObjectManager')->getRepository('Foo/Entity/Bar');
        return $repository->getCountiesAsArrayKeyedByCountyName();
    }
}

通过在 Module.phpmodule.config.php 中添加新条目,向服务管理器注册新元素。

// Module.php
public function getFormElementConfig()
{
    return array(
        'factories' => array(
            'MyModule'Form'Element'CountiesByNameSelect'
                => 'MyModule'Form'Element'CountiesByNameSelectFactory',
        ),
    );
}

最后,更改表单并删除当前选择元素并添加新元素(使用您在服务管理器中注册的名称作为类型键(

$this->add(array(
    'name' => 'counties',
    'type' => 'MyModule'Form'Element'CountiesByNameSelect',
));

它可能看起来像更多的代码(因为它是(,但是您将受益于它更清晰的关注点分离,您现在可以在多个表单上重用该元素,并且只需要在一个地方配置它。