Как передать экземпляр в класс валидатора формы Symfony? - PullRequest
2 голосов
/ 16 октября 2019

Я пытаюсь создать пользовательское ограничение валидатора формы 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 не будет введен таким образом. Что делать?

Ответы [ 2 ]

1 голос
/ 17 октября 2019

Ваша услуга customEmailUniqueEntity никогда не будет учтена ContainerConstraintValidatorFactory, когда она определит фактический валидатор, который будет использоваться для ограничения EmailExists.

Для того, чтобы сообщить фабрике, какие услугиявляются валидаторами ограничений, вам нужно пометить их тегом validator.constraint_validator следующим образом:

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;

$container = new ContainerBuilder();
$container
    ->register('customEmailUniqueEntity', 'EmailExistsValidator')
    ->addArgument($em)
    ->addTag('validator.constraint_validator');
$container->addCompilerPass(new AddConstraintValidatorPass());
$container->compile();
0 голосов
/ 16 октября 2019

Ограничения не являются валидаторами. Symfony возьмет ограничение и найдет его валидатор, прикрепив Validator к имени класса. Таким образом, в Symfony вы регистрируете ограничение по EmailExists, но класс / сервис, который фактически выполняет проверку, равен EmailExistsValidator. И это также место для добавления EntityManagerInterface в него.

Вся информация может быть найдена здесь: Symfony - Как создать пользовательское ограничение проверки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...