我需要一个需要查询数据库的验证器。这意味着我必须创建一个Constraint ConstraintValidator并设置一个服务来注入EntityManager。
我做到了,并研究了官方文档和大量帖子,但无法使其发挥作用。似乎validatedBy()无法启动服务(然后注入EntityManager)。
以下是我挣扎的代码:
validator.frontend.class:
class: Project\UsersBundle\Validation\Constraints\ConstrainsActiveValidator
arguments: [@doctrine.orm.entity_manager]
tags:
- { name: validator.constrain_validator, alias: the_alias }
namespace Project\UsersBundle\Validation\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* */
class ConstrainsActive extends Constraint
{
public function validatedBy()
{
return 'the_alias'; // get_class($this).'Validator';
}
}
namespace Project\UsersBundle\Validation\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Doctrine\ORM\EntityManager;
class ConstrainsActiveValidator extends ConstraintValidator
{
protected $em;
public function __construct(EntityManager $v)
{
$this->em = $em;
}
public function validate($value, Constraint $constraint)
{
$this->context->buildViolation('This name sounds totally fake2!')
->atPath('useEmail')
->addViolation();
}
}
更新:
感谢错字问题。在调整代码到此处发布时,这是一个错误。我解决了! :)
在这里,我总是得到错误:
Attempted to load class "the_alias" from the global namespace in /var/www/Project/current/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php line 71. Did you forget a use statement for this class?
我暂时编辑了文件ConstraintValidatorFactory.php,并为var $ this->验证器做了一个var_dump并得到了响应:
array (size=4)
'validator.expression' => string
'validator.expression' (length=20)
'Symfony\Component\Validator\Constraints\EmailValidator' => string
'validator.email' (length=15) 'security.validator.user_password' =>
string 'security.validator.user_password' (length=32)
'doctrine.orm.validator.unique' => string
'doctrine.orm.validator.unique' (length=29)
似乎symfony框架没有考虑别名" the_alias"在我的自定义服务validator.frontend.class中设置,因为它没有进入var_dump。
我希望这可以给你一些线索。谢谢!
答案 0 :(得分:0)
您的代码没问题,请检查construct
方法中的拼写错误,您将EntityManager命名为$ v,并将其设为$ m。
将ConstrainsActiveValidator
类的构造更改为:
public function __construct(EntityManager $v)
{
$this->em = $v;
}
你有什么错误?
答案 1 :(得分:0)
仅适用于有同样问题的人。我终于决定在一个类型中设置检查表单参数,我的意思是:
Bundle/Form/addType.php
向$builder
对象添加事件侦听器:
public function buildForm(FormBuilderInterface $builder, array $options) {
...
$builder->addEventListener(FormEvents::POST_SUBMIT, function ($event) {
$data = $event->getData();
$form = $event->getForm();
if (null === $data) return;
// Checking comes here!!!
// ......
}
}
在我看来,验证器很棒但是当项目变大时,检查事件内部的信息是最好的方法。您还可以使用一些提供symfony作为EmailConstraints的约束:
use Symfony\Component\Validator\Constraints\Email as EmailConstraint;
答案 2 :(得分:0)
回答自己。让我们验证博客中的帖子输入的slug是唯一的:
假设我们有一个名为AppBundle的包
1)在src / AppBundle中创建子文件夹结构“Validator / Contraints”。
2)在... / Validator / Constraints内,创建一个名为SlugUnique.php的文件(约束):
namespace AppBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*/
class SlugUnique extends Constraint
{
public $message = 'Slug "{{ slug }}" already taken';
public function getTargets()
{
return array(self::PROPERTY_CONSTRAINT);
}
public function validatedBy()
{
return 'app.validator.blog.slug_unique';
}
}
3)在同一文件夹级别创建一个名为SlugUniqueValidator.php的文件(约束验证器):
namespace AppBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Doctrine\ORM\EntityManager;
use AppBundle\Entity\Blog as BlogEntity;
/**
* @Annotation
*/
class SlugUniqueValidator extends ConstraintValidator
{
/** @var EntityManager */
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function validate($value, Constraint $constraint)
{
/** @var BlogEntity $blogEntity */
$blogEntity = $this->context->getRoot()->getViewData();
if (null !== $this->em->getRepository('AppBundle:Blog')->findBy(['slug' => $blogEntity->slug])) {
$this->context->buildViolation($blogEntity->slug)
->atPath('slug')
->addViolation();
}
}
}
4)使用正确的标记项创建services.yml的条目:
app.validator_constraints_blog.slug_unique_validator:
class:AppBundle\Validator\Constraints\SlugUniqueValidator
arguments: ['@doctrine.orm.entity_manager']
tags:
- { name: 'validator.constraint_validator', alias: 'app.validator.blog.slug_unique' }
请注意,alias参数的值必须与SlugUnique类约束中validatedBy返回的值匹配。
5)最后,将此类验证分配给相应的实体字段:
namespace AppBundle\Entity;
use AppBundle\Validator\Constraints as ValidatorConstraints;
class Blog
{
...
/**
* @var string
*
* @ORM\Column(name="slug", type="string", length=255, nullable=false)
* @ValidatorConstraints\SlugUnique
*/
private $slug;
public getSlug()
...
请注意,根据Entity fieldName和表单fieldName,您可能必须在构建表单类型时设置参数“property_path”。例如:
$builder->add(
'slug', TextType::class,
array('required' => false, 'property_path' => 'slug')
);
请注意,您可以将自定义服务注入SlugUniqueValidator而不是EntityManager,以便更好地分离关注点和最佳实践。