4

DoctrineModule\Validator\NoObjectExists在用于编辑的 Zend 表单中使用验证器的最有效方法是什么?因为当我使用相同的表单来保存编辑的值时,这会验证对象的存在和标志表单是无效的。

4

3 回答 3

6

几周前,我在自定义过滤器中使用辅助方法解决了同样的问题。我不确定这是否是正确的方法,但它有效。

  1. 编写一个自定义输入过滤器扩展Zend\InputFilter\InputFilter.
  2. 在过滤器方法中添加您的通用过滤器和验证init()器。
  3. 在输入过滤器中编写一个辅助方法,将教义的存在验证器附加到当前验证器链,如下所示。
  4. 创建新对象时将存在验证器添加到您的过滤器实例,编辑时使用通用过滤器实例。

所以,

<?php
/**
 * Baz filter
 */
class BazFilter extends Zend\InputFilter\InputFilter
{

/**
 * This method will be triggered automatically when you retrive baz filter via inputfiltermanager.
 */
public function init() 
{
    // Define your input names, types, validators and filters as arrays
    $this->add(array(
        'name' => 'code',
        'required' => true,
        'validators' => array(),
        'filters' => array()
    ));

    $this->add( array(...) );
    $this->add( array(...) );
    // ...
}

/**
 * Appends doctrine's noobjectexists validator to validator chain only when required.
 * 
 * @access public
 * @param \Doctrine\ORM\EntityRepository $repository
 * @return \Zend\InputFilter\InputFilter
 */
public function appendExistenceValidator(\Doctrine\ORM\EntityRepository $repository)
{
     $validatorSignature = array(
        'name' => 'code',
        'validators' => array(
            array(
                'name' => 'DoctrineModule\Validator\NoObjectExists',
                'options' => array(
                    'object_repository' => $repository,
                    'fields' => 'code',
                    'messages' => array( NoObjectExists::ERROR_OBJECT_FOUND => "This object with code already exists in database." )
                )
            )
        )
    );
    $validator = $this->getFactory()->createInput( $validatorSignature );
    $this->add($validator);
    return $this;
    }
}

最后,在编辑时将此输入过滤器附加到您的表单中:

// $form = your form instance
// $filter = Bazfilter instance
$form->setData($postData)->setInputFilter( $filter );
if( $form->isValid() === false ) {
    // ...
}

创建时:

// $filter = bazfilter instance
$repository = $entityManager->getRepository('Your\Entity\Name');
$filter->appendExistenceValidator( $repository ); // <-- Notice this line

$form->setData($postData)->setInputFilter( $filter );
if( $form->isValid() === false ) {
    // ...
}
于 2013-05-29T11:13:55.040 回答
1

您不能以简单的方式使用 NoObjectExists,而应使用 UniqueObject:

https://github.com/doctrine/DoctrineModule/blob/ea9e6902fd24906250d01d31561454451a788f86/src/DoctrineModule/Validator/UniqueObject.php

于 2014-01-16T17:50:17.110 回答
0

我尝试在表单中使用 DoctrineModule\Validator\NoObjectExists ,它会阻止保持唯一字段不变的更新。正如@Tadej 提到的 - 使用 UniqueObject。这是一个示例表格:

class ExampleForm extends Form implements InputFilterProviderInterface
{
    /**
    * @var EntityManager
    */
    private $entityManager;

    /**
    * @var Repository
    */
    private $repository;

    /**
    * ExampleForm constructor.
    *
    * @param EntityManager $entityManager
    * @param Repository $repository
    */
    public function __construct(EntityManager $entityManager, Repository $repository)
    {
        $this->entityManager = $entityManager;
        $this->repository    = $repository;
        $this->add(
            [
                'type'       => Text::class,
                'name'       => 'name',
                'options'    => [
                    'label' => _('Name *')
                ],
                'attributes' => [
                    'class' => 'form-control',
                ],
            ]
        );
    }

    /**
    * @return array
    */
    public function getInputFilterSpecification()
    {
        return [
            'name'     => [
                'required'   => true,
                'filters'    => [
                ],
                'validators' => [
                    [
                        'name'    => UniqueObject::class,
                        'options' => [
                            'object_manager'    => $this->entityManager,
                            'object_repository' => $this->repository,
                            'fields'            => ['name'],
                            'use_context'       => true,
                            'messages'          => [
                                UniqueObject::ERROR_OBJECT_NOT_UNIQUE => "Name '%value%' is already in use",
                            ]
                        ]
                    ]
                ]
            ],
        ];
    }
}

注意“use_context”选项的使用——如果字段不是主键,则必须使用它。“消息”是可选的。

于 2016-11-09T10:19:01.993 回答