在 ZF2 FieldSet 中至少需要一个元素

Require at least one element in ZF2 FieldSet

问题

我有一个 Form 和一个 FieldSet。我想验证 FieldSet 是否为空。另外,我想验证 FieldSet.

中的每个字段

到目前为止,无论我尝试过什么,都是验证其中之一,而不是两者。如果 elements 出现在表单的输入过滤器规范中,那么它会验证 elements 不为空,但不会验证 [=13= 的 barbaz 字段].当然,反之亦然。任何有关如何解决此问题的线索都将不胜感激。

形式

class FooForm extends Form implements InputFilterProviderInterface
{
    public function init()
    {
        $this->add([
            'name'     => 'elements',
            'type'     => Collection::class,
            'required' => true,
            'options'  => [
                'target_element' => [
                    'type' => SomeElementFieldSet::class
                ]
            ]
        ]);
    }

    public function getInputFilterSpecification()
    {
        return [
            [
                'name'        => 'elements',
                'required'    => true,
                'validators'  => [
                    ['name' => 'NotEmpty']
                ]
            ]
        ];
    }
}

字段集

class SomeElementFieldSet extends Fieldset implements InputFilterProviderInterface
{
    public function init()
    {
        $this->add(['name' => 'bar']);
        $this->add(['name' => 'baz']);
    }

    public function getInputFilterSpecification()
    {
        return [
            [
                'name'       => 'bar',
                'required'   => true,
                'validators' => [
                    ['name' => 'NotEmpty']
                ]
            ],
            [
                'name'       => 'baz',
                'required'   => true,
                'validators' => [
                    ['name' => 'NotEmpty']
                ]
            ]
        ];
    }
}

编辑:添加了完整的验证规范。

通过指定要验证的输入字段数组,在 Form 对象中使用 setValidationGroup() 方法。请参考Doc!

你可以这样试试。虽然我在表单中添加了一些额外的字段仅用于测试目的。

class FooForm extends Form implements InputFilterProviderInterface
{
     public function __construct($name = null, $options = array())
     {

        parent::__construct($name, $options);

        $this->add(['name' => 'title']);

        $this->add([
            'name'     => 'elements',
            'type'     => Collection::class,
            'required' => true,
            'options'  => [
                'target_element' => [
                    'type' => SomeElementFieldSet::class,
                ],
            ],
        ]);

        $this->add([
            'type' => 'submit',
            'name' => 'submit',
            'attributes' => [
                 'value' => 'Post'
            ],
        ]);

        // I pointed this. Here you can specify fields to be validated
        $this->setValidationGroup([
            'title',
            'elements' => [
                'bar',
            ],
        ]);         
     }

    public function getInputFilterSpecification()
    {
        return [
            [
                'name'       => 'title',
                'required'   => true,
                'validators' => [
                    ['name' => 'NotEmpty']
                ]
            ],
        ];
    }     
}

你的字段集 class 应该是

class SomeElementFieldSet extends Fieldset implements InputFilterProviderInterface
{
    public function init()
    {
        $this->add(['name' => 'bar']);
        $this->add(['name' => 'baz']);
    }

    public function getInputFilterSpecification()
    {
        return [
            [
                'name'       => 'bar',
                'required'   => true,
                'validators' => [
                    ['name' => 'NotEmpty']
                ]
            ],
            [
                'name'       => 'baz',
                'required'   => true,
                'validators' => [
                    ['name' => 'NotEmpty']
                ]
            ]
        ];
    }
} 

希望这会有所帮助!

在 Google 上获得一些提示并深入研究源代码后,我找到了解决方案。不幸的是,zend-inputfilter 的实现有点问题,不能很好地与 getInputFilterSpecification() 一起使用,但我们可以直接构建自己的 InputFilter 和 return:

形式

class FooForm extends BaseForm
{
    public function init()
    {
        $this->add([
            'name'    => 'elements',
            'type'    => Collection::class,
            'options' => [
                'target_element' => [
                    'type' => SomeElementFieldSet::class
                ]
            ]
        ]);
    }

    public function getInputFilter()
    {
        if (!$this->filter) {
            $this->filter = new InputFilter();

            /** @var Collection $elementsCollection */
            $elementsCollection = $this->fieldsets['elements'];

            /** @var SomeElementFieldSet $elementsFieldSet */
            $elementsFieldSet = $elementsCollection->getTargetElement();

            $collectionFilter = new CollectionInputFilter();
            $collectionFilter->setIsRequired(true);
            $collectionFilter->setInputFilter(
                $elementsFieldSet->getInputFilterSpecification()
            );

            $this->filter->add($collectionFilter, 'elements');
        }

        return $this->filter;
    }
}

这将验证集合中至少有一个元素。并且会按照FieldSet的规范一一验证所有的元素。

但仍然存在一个问题。每当集合为空时,验证将 return false,但不会 return 任何消息。这是由于 zend-inputfilter 组件中的错误。报告的问题 here and here。但这完全是另一个问题。