Search code examples
phpsymfonysymfony4symfony-forms

Symfony User Registration Form Validation Errors


I have developed a basic user registration form following the Symfony documentation. I am receiving validation errors when attempting to submit the form that the password and failed login count cannot be null:

data.password       This value should not be null
data.failedLogins   This value should not be null

RegistrationFormType class:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('firstname', TextType::class, ['label'=> false, 'attr' => ['placeholder' => 'First name']])
        ->add('lastname', TextType::class, ['label'=> false, 'attr' => ['placeholder' => 'Last name']])
        ->add('email', EmailType::class, ['label'=> 'Email address', 'attr' => ['placeholder' => 'Email address']])
        ->add('plainPassword', PasswordType::class, [
            'label' => 'Password',
            'attr' => ['placeholder' => 'Must be at least 6 characters'],
            'mapped' => false,
            'constraints' => [
                new NotBlank([
                    'message' => 'Please enter a password',
                ]),
                new Length([
                    'min' => 6,
                    'minMessage' => 'Your password should be at least {{ limit }} characters',
                    // max length allowed by Symfony for security reasons
                    'max' => 4096,
                ]),
            ],
        ])
    ;
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => User::class,
    ]);
}

User entity:

/**
* @var string The hashed password
* @ORM\Column(name="password", type="string", length=255, nullable=false, options={"fixed"=true})
*/
private $password;

/**
 * @var int
 *
 * @ORM\Column(name="failed_logins", type="integer", nullable=false)
 */
private $failedLogins;

Controller:

public function register(Request $request, 
                         UserPasswordEncoderInterface $passwordEncoder, 
                         GuardAuthenticatorHandler $guardHandler, 
                         LoginFormAuthenticator $authenticator): Response
{
    $user = new User();
    $form = $this->createForm(RegistrationFormType::class, $user);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        $user->setPassword($passwordEncoder->encodePassword($user, $form->get('plainPassword')->getData()));
        $user->setfailedLogins(0);

The issue seems to be that the form validator is returning false because it is expecting the 'password' and 'failedLogins' fields. As shown in the code sample, I would like to not include in these fields in the form and address them after the form is submitted...

If I add dummy hidden fields to the form builder, then the form processes fine:

->add('password', HiddenType::class, ['data' => 'abc'])
->add('failedLogins', HiddenType::class, ['data' => 0])

However that does not seem like the correct approach. Any insight as to why these fields are being validated when not included in the form builder would be very much appreciated.


Solution

  • I believe you have 2 different problems, both of them because the validation is done against the entity related to the form.

    From the Form Validation docs:

    Symfony, validation is applied to the underlying object (e.g. Task). In other words, the question isn't whether the "form" is valid, but whether or not the $task object is valid after the form has applied the submitted data to it. Calling $form->isValid() is a shortcut that asks the $task object whether or not it has valid data.


    1. Your password is named password in the entity User, but plainPassword in the form. The validation function will not find a property plainPassword in the entity and return data.password This data should not be null. So, you can just change the form field name to password

    2. You have a failedLogins in your entity, but it does not exist in the form. Form validation checks against all entity's properties by default. As failedLogins is declared as nullable=false, the validation will return data.failedLogins This data should not be null. In this case you need Validation Groups that allow you to choose which properties of User will be considered in the form validation.