I’m using Symfony 5.3.7, and using the @Assert annotations, attempting to validate a new user upon registering. Trying to understand the docs however not getting anywhere. Ideally I’d like to be able to understand how to validate an entity using these annotations. I’ve tried using a separate class, and got nowhere with understanding, although I do want to go down this route in case i reuse the component elsewhere. (I’d rather not validate in the form, but if i have to I can) Entity
class User implements UserInterface { use TimestampableEntity; /** * @var int * * @ORMId() * @ORMGeneratedValue(strategy="IDENTITY") * @ORMColumn(name="intUserId", type="integer", nullable=false) */ private int $id; /** * @var string * * @ORMColumn(name="strFirstName", type="string", nullable=false) * * @AssertNotBlank * @AssertLength( * min = 2, * max = 50, * minMessage = "Your first name must be at least {{ limit}} characters long", * maxMessage = "Your first name cannot be longer than {{ limit }} characters" * ) */ private string $firstName; /** * @var string * * @ORMColumn(name="strLastName", type="string", nullable=false) * * @AssertNotBlank * @AssertLength( * min = 2, * max = 50, * minMessage = "Your first name must be at least {{ limit}} characters long", * maxMessage = "Your first name cannot be longer than {{ limit }} characters" * ) */ private string $lastName; /** * @var string * * @ORMColumn(name="strUsername", type="string", nullable=false) * * @AssertUnique() * @AssertLength( * min = 2, * max = 15, * minMessage = "Your first name must be at least {{ limit}} characters long", * maxMessage = "Your first name cannot be longer than {{ limit }} characters" * ) */ private string $username; /** * @var string * * @ORMColumn(name="strPassword", type="string", nullable=false) * * @AssertNotNull() * @AssertRegex(pattern = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$") * * @SecurityAssertUserPassword(message = "Password is incorrect, please try again") */ private string $password; /** * @var string * * @ORMColumn(name="strEmail", type="string", nullable=false) * * @AssertUnique() * @AssertRegex(pattern = "b[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}b") */ private string $email; /** * @var boolean * * @ORMColumn(name="bolAcceptTermsConditions", type="bool", nullable=false) * * @AssertNotNull() */ private bool $acceptTermsAndConditions; /** * @var boolean * * @ORMColumn(name="bolAcceptPrivacyPolicy", type="bool", nullable=false) * * @AssertNotNull() */ private bool $acceptPrivacyPolicy; /** * @var boolean * * @ORMColumn(name="bolEmailOptIn", type="bool", nullable=false) * * @AssertNotNull() */ private bool $emailOptIn; /** * User constructor. * * @param string $firstName * @param string $lastName * @param string $username * @param string $email * @param string $password */ public function __construct( string $firstName, string $lastName, string $username, string $email, string $password, bool $acceptTermsAndConditions = false, bool $acceptPrivacyPolicy = false, bool $emailOptIn = false ) { $this->firstName = $firstName; $this->lastName = $lastName; $this->username = $username; $this->email = $email; $this->password = $password; $this->acceptTermsAndConditions = $acceptTermsAndConditions; $this->acceptPrivacyPolicy = $acceptPrivacyPolicy; $this->emailOptIn = $emailOptIn; $this->dtmAdded = Carbon::now(); }
Ideally I’d pass in the new entity or the array, either create the entity in the validator or similar Controller
public function register(Request $request): Response { $registrationForm = $this->createForm(RegistrationFormType::class); $registrationForm->handleRequest($request); if ($registrationForm->isSubmitted() && $registrationForm->isValid()) { $newUserData = $registrationForm->getData(); $user = new User( $newUserData['firstName'], $newUserData['lastName'], $newUserData['email'], $newUserData['username'], $newUserData['password'], $newUserData['termsConditions'], $newUserData['privacyPolicy'], $newUserData['emailFrequency'] ); return new RedirectResponse($request->headers->get('referer')); } return new RedirectResponse($request->headers->get('referer')); }
Form
<?php declare(strict_types=1); namespace AppForm; use SymfonyComponentFormAbstractType; use SymfonyComponentFormExtensionCoreTypeCheckboxType; use SymfonyComponentFormExtensionCoreTypeChoiceType; use SymfonyComponentFormExtensionCoreTypeEmailType; use SymfonyComponentFormExtensionCoreTypePasswordType; use SymfonyComponentFormExtensionCoreTypeTextType; use SymfonyComponentFormFormBuilderInterface; use SymfonyComponentOptionsResolverOptionsResolver; class RegistrationFormType extends AbstractType { public const FORM_NAME = 'registrationForm'; /** * Form Builder for Registration Form * * @param FormBuilderInterface $builder * @param array $options * * @return void */ public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->add('firstName', TextType::class, [ 'label' => 'Firstname:', 'required' => true, 'attr' => [ 'class' => 'form-input input-type-text', 'placeholder' => 'John', ], ]); $builder->add('lastName', TextType::class, [ 'label' => 'Lastname:', 'required' => true, 'attr' => [ 'class' => 'form-input input-type-text', 'placeholder' => 'Doe' ], ]); $builder->add('email', EmailType::class, [ 'label' => 'Email:', 'required' => true, 'attr' => [ 'class' => 'form-input input-type-email', 'placeholder' => 'example@example.com' ] ]); $builder->add('username', TextType::class, [ 'label' => 'Username:', 'required' => true, 'attr' => [ 'class' => 'form-input input-type-text', ] ]); $builder->add('password', PasswordType::class, [ 'label' => 'Password:', 'required' => true, 'attr' => [ 'class' => 'form-input input-type-email', ] ]); $builder->add('termsConditions', CheckboxType::class, [ 'label' => 'I accept the terms & conditions', 'required' => true, ]); $builder->add('privacyPolicy', CheckboxType::class, [ 'label' => 'I have read and understood the privacy policy', 'required' => true, ]); $builder->add('emailFrequency', ChoiceType::class, [ 'label' => 'Opt in to emails:', 'multiple' => false, 'expanded' => true, 'choices' => [ 'Yes' => true, 'No' => false, ], ]); } /** * @param OptionsResolver $resolver * * @return void */ public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([]); } /** * @return string */ public function getBlockPrefix(): string { return self::FORM_NAME; } }
Advertisement
Answer
so the issue is that you are not passing the new User object to the form, so the validation will not happen in this case.
What you can do to fix this is, declare the data_class for the form to be User in this case
public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => User::class, ]); }
And when you create the form in the action you need to pass a new User object to it like:
$user = new User(); $registrationForm = $this->createForm(RegistrationFormType::class, $user);
And you can remove the part where you instantiate and send data to the user entity
$user = new User( $newUserData['firstName'], $newUserData['lastName'], $newUserData['email'], $newUserData['username'], $newUserData['password'], $newUserData['termsConditions'], $newUserData['privacyPolicy'], $newUserData['emailFrequency'] );
instead of that, you should just use the entity manager to save the new user , for that, you need to inject the entity manager, like so:
public function register(Request $request, EntityManagerInterface $entityManager): Response
and just use it to save the user object into the database
if ($registrationForm->isSubmitted() && $registrationForm->isValid()) { $entityManager->persist($user); $entityManager->flush(); }