Symfony2: my form returns false from isValid() but empty array for getErrors() from unique constraint condition
Solution 1
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.
Solution 2
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)
Solution 3
The following solutions works for me:
$form->getErrors(true)
Solution 4
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);
}
}
}
Boris_bulletdodger
Updated on November 05, 2020Comments
-
Boris_bulletdodger over 3 years
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: ~
-
Jean-Christophe Meillaud almost 9 yearsgetErrorsAsString is Deprecated since version 2.5, to be removed in 3.0. Use getErrors()} instead and cast the result to a string.
-
contrebis over 8 years
$editForm->getErrors(true)
will now return form errors from children recursively (since 2.5). -
ChristoKiwi over 8 years@DénesPapp pass the optional Boolean param to cascade through any child forms $form->getErrors(true);
-
Roubi over 8 yearsWith more recent Symfony versions, you must use
$form->getErrors(true, false);
instead. First param corresponds to deep and second to flatten