Я пытаюсь создать пользовательское ограничение валидатора формы Symfony. Я создал два класса, одно ограничение и один валидатор, и он отлично работает. Но мне нужно передать экземпляр Doctrine EntityManager в класс валидатора, так как я использую их отдельно, а не в фреймворке, у меня нет файла конфигурации yaml. Я создал конструктор в классе валидатора, чтобы иметь $ em, и в контроллере у меня есть:
->add('email', EmailType::class, [
'constraints' => [
new Assert\Email(['message' => 'invalid.email', 'mode' => 'strict', 'normalizer' => 'trim']),
new Assert\EmailExists($em),
],
]);
Но я не получаю $ em, в моем классе валидатора, что мне делать? Я также пытался иметь конструктор в классе основных ограничений, затем в валидаторе у меня был parent::construct()
, все еще не работающий.
Я тоже читал это Как настроить зависимости для пользовательского валидатора с Symfony Components? но вместо создания фабричного класса я использовал текущий фактор-класс и использовал это:
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Validator\ContainerConstraintValidatorFactory;
$container = new ContainerBuilder();
$container
->register('customEmailUniqueEntity', 'EmailExistsValidator')
->addArgument($em);
$validatorBuilder = Validation::createValidatorBuilder();
$validatorBuilder->setConstraintValidatorFactory(
new ContainerConstraintValidatorFactory($container)
);
$validator = $validatorBuilder->getValidator();
$violations = $validator->validate('email address', [
new EmailExists()
]);
if (0 !== count($violations)) {
// there are errors, now you can show them
foreach ($violations as $violation) {
echo $violation->getMessage().'<br>';
}
}
С этим кодом и внедрение зависимостей, и проверка правильности работают нормально, но есть ли хитрость, чтобы иметь это пользовательское ограничениекак аргумент массива ограничений в конструкторе форм, а не проверять его вручную?
->add('email', EmailType::class, [
'constraints' => [
new Assert\Email(['message' => 'invalid.email', 'mode' => 'strict', 'normalizer' => 'trim']),
new Assert\EmailExists($em),
],
]);
С кодом выше я не могу передать $ em конструктору моего пользовательского Validator. Любой возможный трюк?
РЕДАКТИРОВАТЬ:
Чтобы ввести доктрину EntityManager, в EmailExists
классе у меня было:
public function validatedBy()
{
return 'customEmailUniqueEntity';
//return \get_class($this).'Validator';
}
тогда у меня было:
$container = new ContainerBuilder();
$container
->register('customEmailUniqueEntity', 'EmailExistsValidator')
->addArgument($em);
потому что, если бы я возвращал класс валидатора из validatedBy()
, я бы не смог внедрить $ em в конструктор валидатора. С ответом ниже я использовал:
->addTag('validator.constraint_validator');
Но теперь я получаю ошибку customEmailUniqueEntity
class not found, как будто я возвращаю валидатор из validatedBy()
, инъекция не будет работать, что мне делать? Я пытался вернуть
public function validatedBy()
{
return 'EmailExists';
//return \get_class($this).'Validator';
}
, но этот, конечно, я получаю initialize()
ошибку. Пожалуйста, сообщите.
EDIT2:
Я добавил addTag к:
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Validator\ContainerConstraintValidatorFactory;
$container = new ContainerBuilder();
$container
->register('customEmailUniqueEntity', 'EmailExistsValidator')
->addArgument($em),
->addTag('validator.constraint_validator');
$validatorBuilder = Validation::createValidatorBuilder();
$validatorBuilder->setConstraintValidatorFactory(
new ContainerConstraintValidatorFactory($container)
);
$validator = $validatorBuilder->getValidator();
$violations = $validator->validate('email address', [
new EmailExists()
]);
if (0 !== count($violations)) {
// there are errors, now you can show them
foreach ($violations as $violation) {
echo $violation->getMessage().'<br>';
}
}
и в конструкторе EmailExistsValidator у меня есть:
var_dump($em);
и яЯ получил объект $ em в валидаторе, поэтому $ em вводится и добавление addTag()
не вызывает никаких ошибок. Если я удаляю validatedBy()
из EmailExists
контраста, инъекция не будет сделана. В этом методе я делаю
return `customEmailUniqueEntity;`
, потому что если я верну EmailExistsValidator
, инъекция не будет выполнена. Теперь, как использовать validator.constraint_validator
или EmailExists()
в качестве параметра массива параметров вида? если я использую new EmailExists()
, я получу два агента для класса валидатора, так как $ em не будет введен таким образом. Что делать?