ZF2 + DoctrineModule:允许 Doctrine Form Element ObjectSelect 为空

ZF2 + DoctrineModule: Allow Doctrine Form Element ObjectSelect to be empty

我的一个实体有一个 Zend\Form\Form,它使用 DoctrineModule\Form\Element\ObjectSelect 元素使用户能够 select 引用的实体。

class MyEntityForm extends Zend\Form\Form
{
    public function __construct()
    {
        // ...
        $this->add([
            'name' => 'referenced_entity',
            'type' => 'DoctrineModule\Form\Element\ObjectSelect',
            'options' => [
                'object_manager' => $object_manager,
                'target_class' => 'MyOtherEntity',
                'property' => 'id',
                'display_empty_item' => true
            ],
        ]);
        // ...
    }
 }

引用的实体可能为空(=数据库中的外键字段可以是NULL)。如果没有引用的实体被 selected,我就无法获取表单来验证。即使给定的 referenced_entity 为空(null"")或根本不存在(数据数组中缺少键 referenced_entity),我也希望我的表单能够验证。

我尝试了各种不同的输入滤波器规格,最后的设置如下

class MyEntityForm
    extends Zend\Form\Form
    implements Zend\InputFilter\InputProviderInterface
{
    // ...
    public function getInputSpecification()
    {
        return [
            // ...
            'referenced_entity' => [
                'required' => false,
                'allow_empty' => true,
                'continue_if_empty' => false
            ],
            // ...
    }
    // ...
}

但无济于事,验证错误保持不变($form->isValid()之后$form->getMessages()的var_dump的摘录)

'referenced_entity' => 
    array (size=1)
      'isEmpty' => string 'Value is required and can't be empty' (length=36)

我是否必须扩展 ObjectSelect 表单元素以更改其输入过滤器规范并删除 isEmpty 验证器,或者是否有更简单的解决方案?

如果我没记错的话,如果你想在你的Formclass中提供输入过滤器配置,那么你必须实现InputFilterProviderInterface接口。 如果您想在元素级别配置它,那么您的 Element class 必须实现 InputProviderInterface 接口

所以这意味着您的表单 class 必须是这样的:

class MyEntityForm
    extends Zend\Form\Form
    implements
        // this... 
        // Zend\InputFilter\InputProviderInterface
        // must be this!
        Zend\InputFilter\InputFilterProviderInterface
{
    // ...
    public function getInputFilterSpecification()
    {
        return [
            // ...
            'referenced_entity' => [
                'required' => false,
                'validators' => [],
                'filters' => [],
            ],
            // ...
    }
    // ...
}

DoctrineModule\Form\Element\ObjectSelect 继承了 Zend\Form\Element\Select 并且它自己自动包含 a input especification with a validator

我没有测试自己,但解决这个问题的方法是通过在选项中添加 'disable_inarray_validator' 键来删除这个验证器:

public function __construct()
{
    // ...
    $this->add([
        'name' => 'referenced_entity',
        'type' => 'DoctrineModule\Form\Element\ObjectSelect',
        'options' => [
            'object_manager' => $object_manager,
            'target_class' => 'MyOtherEntity',
            'property' => 'id',
            'display_empty_item' => true,
            'disable_inarray_validator' => true
        ],
    ]);
    // ...
    //or via method
    $this->get('referenced_entity')->setDisableInArrayValidator(true);
}