Good day! Just started learning Symfony on my own.
I’m making a news portal. The administrator can download news from an Excel file. I am converting a file to an associative array. For example:
[ 'Title' => 'Some title', 'Text' => 'Some text', 'User' => 'example@example.com', 'Image' => 'https://loremflickr.com/640/360' ]
Next, I want to send this array to the form and use ‘constraints’ to validate it. There are no problems with the fields ‘Title’, ‘Text’, ‘Image’. I don’t know how to properly check the ‘User’ field. The user in the file is submitting an Email, but I want to check that a user with that Email exists in the database.
NewsImportType
class NewsImportType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('title', TextType::class, [ 'constraints' => [ new NotBlank(), new Length(['min' => 256]) ], ]) ->add('text', TextareaType::class, [ 'constraints' => [ new NotBlank(), new Length(['max' => 1000]) ], ]) ->add('user', TextType::class, [ 'constraints' => [ new NotBlank(), new Email(), ], ->add('image', TextType::class, [ 'constraints' => [ new NotBlank(), new Length(['max' => 256]), new Url() ], ]); } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'allow_extra_fields' => true, 'data_class' => News::class, ]); } }
The entities User and News are connected by a One-to-Many relationship.
I was thinking about using ChoiceType and calling UserRepository somehow, but I don’t understand how to apply it correctly.
Please tell me how to correctly write ‘constraint’ for the ‘user’ field. thank!
Advertisement
Answer
Create a Custom Constraint. This way it is reusable in any other form you would like to check for a user.
Create a new folder in your project src/Validator
then put these 2 files in there.
The Constraint
// src/Validator/userAccountExists.php namespace AppValidator; use SymfonyComponentValidatorConstraint; class UserAccountExists extends Constraint { public $message = 'User account does't exists. Please check the email address and try again.'; }
The Validator
// src/Validator/userAccountExistsValidator.php namespace AppValidator; use SymfonyComponentValidatorConstraint; use SymfonyComponentValidatorConstraintValidator; use SymfonyComponentValidatorExceptionUnexpectedTypeException; use SymfonyComponentValidatorExceptionUnexpectedValueException; use DoctrineORMEntityManagerInterface; use AppEntityUser; class UserAccountExistsValidator extends ConstraintValidator { private $entityManager; public function __construct(EntityManagerInterface $entityManager) { $this->entityManager = $entityManager; } public function validate($email, Constraint $constraint) { if (!$constraint instanceof UserAccountExists) { throw new UnexpectedTypeException($constraint, UserAccountExists::class); } if (null === $email || '' === $email) { return; } if (!is_string($email)) { throw new UnexpectedValueException($email, 'string'); } if (!$this->userExists($email)) { $this->context->buildViolation($constraint->message)->addViolation(); } } private function userExists(string $email): bool { $user = $this->entityManager->getRepository(User::class)->findOneBy(array('email' => $email)); return null !== $user; } }
In your form you can now use the validator
->add('user', TextType::class, [ 'constraints' => [ new NotBlank(), new Email(), new UserAccountExists(), ],
Remember to add use AppValidatorUserAccountExists;
to your form.