【问题标题】:ZF2 + DoctrineModule: Allow Doctrine Form Element ObjectSelect to be emptyZF2 + DoctrineModule:允许Doctrine Form Element ObjectSelect为空
【发布时间】:2016-11-22 12:40:43
【问题描述】:

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

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)。如果没有选择引用的实体,我只是无法获取表单来验证。即使给定的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->getMessages() 的 var_dump 在$form->isValid() 之后的摘录)

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

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

【问题讨论】:

  • 您是否尝试从 inputSpecification 中删除“allow_empty”和“continue_if_empty”选项,因为它们可能不是必需的。
  • 你用的是什么版本的zend-form?
  • @Kwido 是的,我尝试了多种组合,但都没有奏效
  • @ViníciusFagundes composer.lock 说 zendframework 的 2.4.10 版本(是的,我们还没有从使用整个包更改为只使用我们需要的组件,将在不久的将来完成......)
  • 你试过了吗:required => falseallow_empty => truecontinue_if_empty => true。最后一个与您的问题不同。您是否还确保您保存它的实体也具有referenced_entity 属性注释:* @ORM\Column(name="referenced_entity", nullable=true)(可为空的部分)

标签: php forms validation doctrine-orm zend-framework2


【解决方案1】:

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

所以这意味着你的表单类必须是这样的:

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' => [],
            ],
            // ...
    }
    // ...
}

【讨论】:

  • 我已经扩展了我的MyEntityForm 以包含InputFilterSpecification(请参阅我原始消息中的最后一个列表)。那没有用。我尝试从您的示例中添加 'validators => [], 'filters' => [] 部分,希望这会覆盖由 ObjectSelect 元素类设置的任何过滤器或验证器,但我仍然遇到同样的错误......
  • 您必须实现 InputFilterProviderInterface,而不是 InputProviderInterface。这是两个不同的接口。一个用于元素类,另一个用于表单/字段集类。
  • 对不起,我发送的表格太快了。在此处查看 zf 文档:framework.zend.com/manual/2.0/en/modules/… 在“提示输入过滤器”一章中。因此,请尝试让您的表单类实现 InputFilterProviderInterface(使用方法 getInputFilterSpecification() 方法)因为在您的代码中实现 InputFilterSpecification
  • Heureka,做到了!我从没想过继承是错误的。接口名称如此细微的差异,这绝不会引起我的注意!我一直对这些接口的命名有一种奇怪的感觉,而这个问题只是强化了这种感觉......
  • 需要注意的是,这不仅适用于Forms,也适用于Fieldsets!
【解决方案2】:

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);
}

【讨论】:

  • 不幸的是,这也没有做到。 “isEmpty”验证器仍在执行中。 Select 元素不提供与使用 inArray 验证器相同的功能来禁用 isEmpty 验证器。我想我只需要扩展 ObjectSelect 元素来更改验证器。
猜你喜欢
  • 1970-01-01
  • 2014-06-01
  • 1970-01-01
  • 2015-02-06
  • 2014-05-25
  • 1970-01-01
  • 2012-11-08
  • 1970-01-01
  • 2020-02-07
相关资源
最近更新 更多