17

I have a Customer entity that only has a unique Email field to it. I am trying to edit a customer's email and the validation works fine. However I have this in my controller:

public function updateAction(Request $request, $id) {
    $em = $this->getDoctrine()->getManager();

    $entity = $em->getRepository('AcmeDemoBundle:Customer')->find($id);

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


    $editForm = $this->createForm(new CustomerType(), $entity);
    $editForm->bind($request);
    if ($editForm->isValid()) {
        $em->persist($entity);
        $em->flush();

        return $this->redirect($this->generateUrl('ticket_result'));
    }
    var_dump($editForm->getErrors());

    return $this->render('AcmeDemoBundle:Customer:edit.html.twig', array(
                'entity' => $entity,
                'edit_form' => $editForm->createView(),
    ));
}

The var_dump returns an empty array but the validator sets a unique error and the $editForm->isValid() returns false. Is there a way to check for that specific error in the controller during validation, also can you explain why it returns an empty error array? Basically, I would like to provide the "merge" option if that error comes up.

EDIT: here is the formtype:

namespace Acme\DemoBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CustomerType extends AbstractType {


    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
                ->add('email', 'email', array('required'=>true))
        ;

    }

    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\DemoBundle\Entity\Customer',
            'cascade_validation' => true,
        ));
    }

    public function getName() {
        return 'acme_demobundle_customertype';
    }
}

And the twig template:

{% extends 'AcmeDemoBundle::layout.html.twig' %}
{% block body -%}
    <h1>Customer edit</h1>



  <form action="{{ path('customer_update', { 'id': entity.id }) }}" method="post" {{ form_enctype(edit_form) }}>
        <input type="hidden" name="_method" value="PUT" />
        {{ form_widget(edit_form) }}
        <p>
            <button type="submit">Edit</button>
        </p>
    </form>

{% endblock %}

Here is my validation:

Acme\DemoBundle\Entity\Customer:
    constraints:
      - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: 
          fields: email
          message: "A customer under that email address already exists"

    properties:
        email:
            - Email: ~
3
  • Does your customer type have any sub-forms ? Commented Jul 15, 2013 at 16:43
  • show your template, plz Commented Jul 15, 2013 at 16:53
  • I updated the post and added the validation, template and formtype Commented Jul 16, 2013 at 8:45

6 Answers 6

22

For debug purposes you can use $form->getErrorsAsString() instead of $form->getErrors() if you use Symfony 2.*

Quoted from this answer:

$form->getErrorsAsString() should only be used to debug the form...it will contain the errors of each child elements which is not the case of $form->getErrors().


UPDATE 1:

"With more recent Symfony versions, you must use $form->getErrors(true, false); instead. First param corresponds to deep and second to flatten" (see the comment by @Roubi)

Sign up to request clarification or add additional context in comments.

3 Comments

getErrorsAsString is Deprecated since version 2.5, to be removed in 3.0. Use getErrors()} instead and cast the result to a string.
@DénesPapp pass the optional Boolean param to cascade through any child forms $form->getErrors(true);
With more recent Symfony versions, you must use $form->getErrors(true, false); instead. First param corresponds to deep and second to flatten
5

Ok, found an answer here:

Symfony2 invalid form without errors

It turns out each form child has it's own separate errors. When doing a var_dump of

$editForm->getChildren()['email']->getErrors()

I get:

array (size=1)
  0 => 
    object(Symfony\Component\Form\FormError)[531]
      private 'message' => string 'A customer under that email address already exists' (length=50)
      protected 'messageTemplate' => string 'A customer under that email address already exists' (length=50)
      protected 'messageParameters' => 
        array (size=0)
          empty
      protected 'messagePluralization' => null

I am still wondering how to determine that the error is because of a unique conflict without parsing the error message string.

1 Comment

$editForm->getErrors(true) will now return form errors from children recursively (since 2.5).
3

The following solutions works for me:

$form->getErrors(true)

Comments

1

You can use error_bubbling on each field to bubble the error up to your $form.

If not, you can also foreach through the errors

foreach ($children as $child) {
            if ($child->hasErrors()) {
                $vars = $child->createView()->getVars();
                $errors = $child->getErrors();
                foreach ($errors as $error) {
                    $this->allErrors[$vars["name"]][] = $this->convertFormErrorObjToString($error);
                }
            }
}

Comments

0

In Symfony 2.3, you can use this one :

if ($form->isValid()){
    # Code...
} else {
    foreach ($form->getIterator() as $key => $child) {
        if ($child instanceof Form) {
            foreach ($child->getErrors() as $error) {
                $errors[$key] = $error->getMessage();
            }
        }
    }
}

This will get you an array ($errors) with the errors from the children.

Comments

0

You could try to use the dump function when the form is submited and not valid. I use it like this

if($form->isSubmited() && $form->isValid()){
   //SAVE TO DATABASE AND DO YOUR STUFF
}else if($form->isSubmited()){
  //SUBMITED BUT WITH ERRORS
   dump($form->getErrors(true));
   die();

}

Note this is for debugging purposes only, It will show you your form, the data in it and all the errors any field could have. In production mode you should return the error to the view and show them to the user.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.