我正在学习学说,我有一个表格。 ZF2和学说与字段“电子邮件”。 这个字段必须是唯一的,所以我需要验证器。我也使用了字段集(这里很重要)。问题是,当我使用时:
DoctrineModule\Validator\UniqueObject
创建新实体是不可能的。此验证器需要主键进行比较。 带有消息的验证器转储错误:
包含itemId的预期上下文
itemId是我的主键。
显而易见,我需要使用UniqueObject进行更新,并且:
DoctrineModule\Validator\NoObjectExists
表示新实体。问题是:
为现有实体和新实体存储不同的输入过滤规范的最佳方法是什么?
或者,如果可能的话,更好:如何使用带有zend表单字段集的新记录和现有记录的唯一验证器。
如果我把它放在表单中,我需要在控制器内修改它,如果实体是新的或没有。不太好主意。
我认为最好的方法是存储输入过滤规范。在实体存储库内部,但我如何检查实体是否是新的?
----编辑
我看到了文档,我知道如何使用唯一对象,但我有如前所述的错误:“包含itemId的预期上下文”。我认为问题在于字段集(即时使用它)。我不明白该怎么做(文档中的文字):
如果省略use_context选项或将其设置为false,则必须这样做 将包含fields-和identifier-values的数组传递给 已验证()。使用Zend \ Form时,如果你需要这种行为 使用字段集。
好的我正在使用现场集,所以现在我能做什么?我在使用zend表单时如何将正确的值传递给isValid?
答案 0 :(得分:2)
使用N
验证程序,您需要在上下文中包含标识符字段。因此,仅当UniqueObject
列是email
实体的标识符列时,它才有效吗?您还有一个Email
列。最好在您的用户案例中使用id
验证程序:
NoObjectExists
您还可以找到此示例in the documentation。
关于分离更新和新输入过滤器的逻辑我建议制作两个文件夹。最好将它们严格分开,否则很可能会发生错误。例如,您可以这样做(但这完全取决于您个人喜好如何组织)。
'email' => array(
'validators' => array(
array(
'name' => 'DoctrineModule\Validator\NoObjectExists',
'options' => array(
'object_repository' => $entityManager->getRepository(
'Application\Entity\Email'
),
'fields' => 'email'
)
)
)
)
一个用于更新资源:
Application/InputFilter/Create
UserInputFilter
然后在你的控制器中你可以这样做:
Application/InputFilter/Update
UserInputFilter
答案 1 :(得分:2)
我为我的应用程序开发了它来处理这个问题。希望它会有所帮助
<?php
namespace Application\Validator;
use Zend\Validator\AbstractValidator;
class DbUniqueObject extends AbstractValidator {
const INVALID = 'objectAlreadyExists';
protected $messageTemplates = array(
self::INVALID => "Field value must be unique in the database (id=%id%)",
);
protected $messageVariables = array(
'id' => array('options' => 'id'),
);
protected $options = array(
'em',
'entity',
'field',
'exclude_id'
);
public function __construct($options = null) {
$this->options = $options;
parent::__construct($options);
}
public function isValid($value) {
$qb = $this->em->createQueryBuilder();
$qb->select('t')
->from($this->entity, 't')
->where('t.' . $this->field . '= :field')
->setParameter('field', $value);
if (boolval($this->exclude_id)) {
$qb->andWhere('t.id <> :id');
$qb->setParameter('id', $this->exclude_id);
}
$result = $qb->getQuery()->getResult();
if (boolval($result)) {
$this->options['id'] = $result[0]->getID();
$this->error(self::INVALID);
return false;
}
return true;
}
public function __get($property) {
return array_key_exists($property, $this->options) ? $this->options[$property] : parent::__get($property);
}
}
然后在你的输入过滤器中附加到你的表单,只需添加,在'Validators'数组中:
'validators' => array(
array(
'name' => '\Application\Validator\DbUniqueObject',
'options' => array(
'em' => $em, //Entity manager
'entity' => 'Application\Entity\Customer', // Entity name
'field' => 'label', // column name
'exclude_id' => $this->customer->getID() : null, // id to exclude (useful in case of editing)
)
)
),
答案 2 :(得分:1)
我会展示我的解决方案,如果有人想在表单中保留验证器,我认为相当不错。在我的fieldset中,我有方法getInputFilterSpecification(),它会自动处理,并在那里:
public function getInputFilterSpecification()
{
// im bind object new or exist to the form,
// so there is a simple way to get it:
$entity = $this->getObject();
// method to check if object is new or not:
// $this->_entityManager i have entitymanager passed in constructor
switch ($this->_entityManager->getUnitOfWork()->getEntityState($entity)) {
case \Doctrine\ORM\UnitOfWork::STATE_MANAGED:
// im switch validator, unique for existing:
$existValidator = 'DoctrineModule\Validator\UniqueObject';
case \Doctrine\ORM\UnitOfWork::STATE_NEW:
$existValidator = 'DoctrineModule\Validator\NoObjectExists';
}
// propably we can also check if object primary key is empty or not
// i will test it later
return array(
'elementName' => array(
'required' => true,
'validators' => array(
array(
'name' => $existValidator,
'options' => array(
'object_repository' => $this->_entityManager->getRepository('My\Entity'),
'object_manager' => $this->_entityManager,
'fields' => 'fieldName',
)
)
)
)
);
}
它仍未使用唯一验证器进行测试。也许主键也会有问题,我会在几天内检查一下。但它仍然是基于新节点或现有节点分配正确验证器的简单方法。
我的结论: 唯一验证器不适用于ZF2和字段集。
答案 3 :(得分:0)
您只需要在输入过滤器规范:
中使用UniqueObject验证器,如下所示 'email' => array(
'validators' => array(
array(
'name' => 'DoctrineModule\Validator\UniqueObject',
'options' => array(
'use_context' => true,
'object_repository' => $this->objectManager->getRepository('Namespace\EntityName'),
'object_manager' => $this->objectManager,
'fields' => 'email',
'messages' => array(
'objectNotUnique' => 'Email already exists!'
),
),
)
),
),
您可以从此链接中找到更多详细信息: https://github.com/doctrine/DoctrineModule/blob/master/docs/validator.md