具有依赖关系的 Symfony 验证器

Symfony validator with dependencies

我想用约束注释验证一个对象,并在验证器中使用依赖项(entityManager)。

如果验证器在构造函数中具有依赖项(例如 entityManager),则验证器不起作用。

我遵循了文档,但它不起作用: https://symfony.com/doc/current/validation/custom_constraint.html#constraint-validators-with-dependencies

"ClassNotFoundException 试图从全局命名空间加载 class "validator_question_exists"。 您是否忘记了 "use" 语句?"

我尝试像这样验证 'Question' 对象(也许问题出在这里):

$validator = Validation::createValidatorBuilder()
    ->enableAnnotationMapping()
    ->getValidator()
;

$question = new Question();
$errors = $validator->validate($question);

问题(要验证的对象)

/** @App\Validator\Constraint\Question\QuestionExists() */
class QuestionReadInput{
    ....
}

services.yaml

services:
    validator.unique.question_exists:
        class: App\Validator\Constraint\Question\QuestionExistsValidator
        tags:
            - { name: validator.constraint_validator, alias: validator_question_exists}

约束

namespace App\Validator\Constraint\Question;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class QuestionExists extends Constraint
{
    public $message;

    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }

    public function validatedBy()
    {
        //if i delete this function, symfony cant autowire the entitymanager to the validator
        //this throws an error, wants to make a new validator_question_exists(), which not exists, because its a service alias, the docs said it should be okay
        return 'validator_question_exists';
    }
}

验证者

class QuestionExistsValidator extends ConstraintValidator
{
    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function validate($value, Constraint $constraint)
    {
          die('I dont see this message...');
    }

调试:容器


Information for Service "validator.unique.question_exists"
 ---------------- -------------------------------------------------------------------
  Option           Value
 ---------------- -------------------------------------------------------------------
  Service ID       validator.unique.question_exists
  Class            App\Validator\Constraint\Question\QuestionExistsValidator
  Tags             validator.constraint_validator (alias: validator_question_exists)
                   validator.constraint_validator
  Public           no
  Synthetic        no
  Lazy             no
  Shared           yes
  Abstract         no
  Autowired        yes
  Autoconfigured   yes

如果您自己声明服务,那么您还应该添加它的参数:

services:
    validator.unique.question_exists:
        class: App\Validator\Constraint\Question\QuestionExistsValidator
        arguments: ['@doctrine.orm.entity_manager']
        tags:
            - { name: validator.constraint_validator }

除此之外,它应该可以在没有任何标记别名或 validatedBy 方法的情况下工作。

旁注:很长一段时间以来,在 Symfony 中,建议使用 class 名称来命名(id)您的服务,这样自动连接可以处理您的服务,并且您不需要 class参数,即:

services:
    App\Validator\Constraint\Question\QuestionExistsValidator:
        arguments: ['@doctrine.orm.entity_manager']
        tags:
            - { name: validator.constraint_validator }

正如@xabbuh 提到的,我只是使用了默认的 symfony Validator,它起作用了。

__construct(ValidatorInterface $validator){
    $question = new Question();
    $errors   = $validator->validate($question);
}

我不应该使用 Validaton::createValidatorBuilder 创建自己的验证器。

用这个配置没关系:

App\Validator\Constraint\Question\QuestionExistsValidator:
    tags: ['validator.constraint_validator']

with no validatedBy()

或者:

validator.unique.question_exists:
    class: App\Validator\Constraint\Question\QuestionExistsValidator
    tags:
        - { name: validator.constraint_validator, alias: validator_question_exists}

with:

public function validatedBy() {
    return 'validator_question_exists';
}