【问题标题】:How to use DoctrineModule\Validator\NoObjectExists in edit forms - Zend Framework 2 & Doctrine 2如何在编辑表单中使用 DoctrineModule\Validator\NoObjectExists - Zend Framework 2 & Doctrine 2
【发布时间】:2016-11-09 18:19:01
【问题描述】:

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

【问题讨论】:

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


【解决方案1】:

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

  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 ) {
    // ...
}

【讨论】:

  • 所以,既然你编辑了一个用户,你可以给他一个已经存在的电子邮件......
【解决方案2】:

【讨论】:

  • 看起来不错,但 isValid 清空实体,绑定到表单。
  • 不会使新表单无效。因为数据库中的字段没有唯一记录?
【解决方案3】:

我尝试在表单中使用 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”选项的使用 - 如果字段不是主键,则必须使用它。 “消息”是可选的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-04
    • 2011-12-13
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多