Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to make form ignore password fields if blank (symfony2 forms)

Tags:

forms

php

symfony

I have a simple user manager in my backend, and I want to be able to edit the user without setting a new password/repeating the old password every time.

Right now if I leave the password fields blank when editing a user, symfony2 complains that a password must be entered, and of course I want this functionality when I register new users, but when I edit them, I'd like for the form to just ignore the password boxes if they aren't filled out.

How is this accomplished?

like image 243
Matt Welander Avatar asked Aug 14 '12 21:08

Matt Welander


5 Answers

For someone else's reference, I worked this one out this way.

My formType:

public function buildForm(FormBuilder $builder, array $options)
{   

    $builder
        ->add('username', 'text', array('label' => 'Servernamn '))            
        ->add('plainPassword', 'repeated', array('type' => 'password', 'first_name' => 'Lösenord för server ', 'second_name' => 'Upprepa lösenord för server',));

    $builder-> addValidator(new CallbackValidator(function(FormInterface $form){
      $username = $form->get('username')->getData();
        if (empty($username)) {
          $form['username']->addError(new FormError("Du måste ange ett namn för servern"));
        }
    }));

}

My updateAction:

public function updateServerAction($id)
{
    $em = $this->getDoctrine()->getEntityManager();

    $entity = $em->getRepository('BizTVUserBundle:User')->find($id);

    if (!$entity) {
        throw $this->createNotFoundException('Unable to find Container entity.');
    }

    $originalPassword = $entity->getPassword(); 

    $editForm   = $this->createForm(new editServerType(), $entity);

    $request = $this->getRequest();

    $editForm->bindRequest($request);

    if ($editForm->isValid()) {

        $plainPassword = $editForm->get('plainPassword')->getData();
        if (!empty($plainPassword))  {  
            //encode the password   
            $encoder = $this->container->get('security.encoder_factory')->getEncoder($entity); //get encoder for hashing pwd later
            $tempPassword = $encoder->encodePassword($entity->getPassword(), $entity->getSalt()); 
            $entity->setPassword($tempPassword);                
        }
        else {
            $entity->setPassword($originalPassword);
        }

        $em->persist($entity);
        $em->flush();

        return $this->redirect($this->generateUrl('Server'));
    }

Thus updating my users password should it be set, otherwise keep the original password.

like image 155
Matt Welander Avatar answered Nov 06 '22 03:11

Matt Welander


On your entity setter for the password property make it like this:

/**
 * Set password
 *
 * @param string $password
 * @return User
 */
public function setPassword($password)
{
    if (!is_null($password)) {
        $this->password = $password;
    }

    return $this;
}

The trick is to check if the parameter being passed is empty and only setting if it's not.

like image 33
Diego Castro Avatar answered Nov 06 '22 02:11

Diego Castro


If you need add required option to $options array. Example:

public function buildForm(FormBuilder $builder, array $options)
{   

    $builder
        ->add('username', 'text', array('label' => 'Servernamn '))            
        ->add('plainPassword', 'repeated', array(
                  'type' => 'password', 
                  'first_name' => 'password', 
                  'second_name' => 'repeat_password', 
                  'required' => false,
            ));
}
like image 4
Liutas Avatar answered Nov 06 '22 03:11

Liutas


What I did was to leave the UserType as is and only remove the password field in the controller:

/**
 * @Route("/users/edit/{username}", name="user_edit")
 */
public function editAction(Request $request, User $user)
{
    $form = $this->createForm(UserType::class, $user);

    // Remove the password field when editing the user
    // Otherwise it must be entered each time the user is edited
    // We can change the password via a special edit-user-password page
    $form->remove('password');

    $form->handleRequest($request);

    if ($form->isValid()) {
        // ...
    }
}

This way you can have a single UserType, reusable in the editAction and the newAction.

Be sure to add the line $form->remove('password'); before $form->handleRequest($request);.

like image 2
DelphiLynx Avatar answered Nov 06 '22 02:11

DelphiLynx


There is an article gives many options to achieve your request, from the Symfony2 cookbook, in particular, the section below worked for me:

Customizing your Form based on the underlying Data

Below is the implementation:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...
    $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
        $product = $event->getData();
        $form = $event->getForm();

        // check if the Product object is "new"
        // If no data is passed to the form, the data is "null".
        // This should be considered a new "Product"
        if (!$product || null === $product->getId()) {
            $form->add('name', 'text');
        }
    });
}
like image 1
wesamly Avatar answered Nov 06 '22 02:11

wesamly