简体   繁体   English

如何在编辑表单中使用DoctrineModule \ Validator \ NoObjectExists - Zend Framework 2和Doctrine 2

[英]How to use DoctrineModule\Validator\NoObjectExists in edit forms - Zend Framework 2 & Doctrine 2

What is the most effective way to use DoctrineModule\\Validator\\NoObjectExists validator in a Zend Form that is used for editing also? 在用于编辑的Zend表单中使用DoctrineModule\\Validator\\NoObjectExists验证器的最有效方法是什么? Because when I use the same Form for saving edited values, this validates the Object existence and flags form is invalid. 因为当我使用相同的Form保存编辑的值时,这将验证Object存在并且flags表单无效。

Few weeks ago I resolved the same problem using a helper method in my custom filter. 几周前,我在自定义过滤器中使用辅助方法解决了同样的问题。 I am not sure if this is the correct approach but it works. 我不确定这是否是正确的方法,但它的工作原理。

  1. Write a custom inputfilter extending Zend\\InputFilter\\InputFilter . 编写一个自定义的inputfilter,扩展Zend\\InputFilter\\InputFilter
  2. Add your generic filters and validators at init() method of filter. 在过滤器的init()方法中添加通用过滤器和验证器。
  3. Write a helper method in the input filter which appends doctrine's existence validator to current validator chain like below. 在输入过滤器中编写一个辅助方法,将doctrine的存在验证器附加到当前验证器链,如下所示。
  4. Add existence validator to your filter instance when creating new object, use generic filter instance when editing. 在创建新对象时将存在验证器添加到过滤器实例,在编辑时使用通用过滤器实例。

So, 所以,

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

Finally, append this inputfilter to your form when editing: 最后,在编辑时将此inputfilter附加到表单:

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

When creating: 创建时:

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

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

I tried using DoctrineModule\\Validator\\NoObjectExists in form and it prevents updates which keep the unique field(s) unchanged. 我尝试在表单中使用DoctrineModule \\ Validator \\ NoObjectExists,它会阻止保持唯一字段不变的更新。 As @Tadej mentioned - use UniqueObject. 正如@Tadej所提到的 - 使用UniqueObject。 Here is an example form: 这是一个示例表单:

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",
                            ]
                        ]
                    ]
                ]
            ],
        ];
    }
}

Note the use of 'use_context' option - it must be used if field is not primary key. 请注意使用'use_context'选项 - 如果字段不是主键,则必须使用它。 'messages' is optional. 'messages'是可选的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM