Symfony2: Comment obtenir des erreurs de validation de formulaire après avoir lié la demande au formulaire

110

Voici mon saveActioncode (où le formulaire transmet les données)

public function saveAction()
{
    $user = OBUser();

    $form = $this->createForm(new OBUserType(), $user);

    if ($this->request->getMethod() == 'POST')
    {
        $form->bindRequest($this->request);
        if ($form->isValid())
            return $this->redirect($this->generateUrl('success_page'));
        else
            return $this->redirect($this->generateUrl('registration_form'));
    } else
        return new Response();
}

Ma question est: comment puis-je obtenir les erreurs en cas de $form->isValid()retour false?

putolaruan
la source

Réponses:

117

Vous avez deux façons possibles de le faire:

  • ne pas rediriger l'utilisateur en cas d'erreur et l'afficher {{ form_errors(form) }}dans le fichier modèle
  • accéder au tableau d'erreurs comme $form->getErrors()
nefo_x
la source
22
J'ai fait la deuxième chose que vous avez suggérée mais form-> getErrors () renvoie un tableau vide.
putolaruan
2
J'ai aussi fait le premier (w / php templates <? Php echo $ view ['form'] -> errors ($ form)?>) Mais il est toujours vide!
putolaruan
59
@mives Vous devez définir error_bubblingsur true dans votre type de formulaire en définissant explicitement l'option pour chaque champ.
kgilden
5
Si vous utilisez des validateurs personnalisés, Symfony ne renvoie pas les erreurs générées par ces validateurs dans $ form-> getErrors ().
Jay Sheth
13
Vous pouvez également $form->getErrors(true)inclure les erreurs des formulaires enfants
Chris
103

Symfony 2.3 / 2.4:

Cette fonction récupère toutes les erreurs. Celles du formulaire telles que "Le jeton CSRF n'est pas valide. Veuillez réessayer de soumettre le formulaire." ainsi que des erreurs supplémentaires sur les enfants du formulaire qui n'ont pas de bouillonnement d'erreur.

private function getErrorMessages(\Symfony\Component\Form\Form $form) {
    $errors = array();

    foreach ($form->getErrors() as $key => $error) {
        if ($form->isRoot()) {
            $errors['#'][] = $error->getMessage();
        } else {
            $errors[] = $error->getMessage();
        }
    }

    foreach ($form->all() as $child) {
        if (!$child->isValid()) {
            $errors[$child->getName()] = $this->getErrorMessages($child);
        }
    }

    return $errors;
}

Pour obtenir toutes les erreurs sous forme de chaîne:

$string = var_export($this->getErrorMessages($form), true);

Symfony 2.5 / 3.0:

$string = (string) $form->getErrors(true, false);

Docs:
https://github.com/symfony/symfony/blob/master/UPGRADE-2.5.md#form https://github.com/symfony/symfony/blob/master/UPGRADE-3.0.md#form (à le fond: The method Form::getErrorsAsString() was removed)

Retourner
la source
1
Cela ressemble à la réponse la plus correcte pour Symfony 2.4 actuel.
Slava Fomin II
@Flip ça marche parfaitement sur 2.5
iarroyo
1
Excellente réponse MAIS $errors[$child->getName()] = $this->getErrorMessages($child);lançait une exception, car getErrorMessages était absent du composant Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller . Alors je l'ai remplacé par$form_errors[$child->getName()] = $child->getErrorsAsString();
Ahad Ali
3
@AhadAli est une fonction récursive, donc lorsque vous placez l'extrait de code dans la classe où vous avez besoin de cette fonctionnalité, il pourra s'appeler. Votre "correctif" vous empêchera d'accéder aux formulaires imbriqués. Cela a fonctionné pour 37 autres personnes, cela devrait fonctionner pour vous aussi;)
Retourner le
@Flip Ah désolé mon mal, je ne faisais que regarder $this->getErrorMessages()et je pensais que c'était appelé directement dans un contrôleur et une partie de l'api Symfony.
Ahad Ali le
47

Voici la solution qui a fonctionné pour moi. Cette fonction se trouve dans un contrôleur et renverra un tableau structuré de tous les messages d'erreur et du champ qui les a provoqués.

Symfony 2.0:

private function getErrorMessages(\Symfony\Component\Form\Form $form) {
    $errors = array();
    foreach ($form->getErrors() as $key => $error) {
        $template = $error->getMessageTemplate();
        $parameters = $error->getMessageParameters();

        foreach($parameters as $var => $value){
            $template = str_replace($var, $value, $template);
        }

        $errors[$key] = $template;
    }
    if ($form->hasChildren()) {
        foreach ($form->getChildren() as $child) {
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    }

    return $errors;
}

Symfony 2.1 et plus récent:

private function getErrorMessages(\Symfony\Component\Form\Form $form) {      
    $errors = array();

    if ($form->hasChildren()) {
        foreach ($form->getChildren() as $child) {
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    } else {
        foreach ($form->getErrors() as $key => $error) {
            $errors[] = $error->getMessage();
        }   
    }

    return $errors;
}
Icode4food
la source
5
Amélioration de gist.github.com/2011671 mais toujours pas ce que je veux. Je veux que les clés de tableau soient des noms de champ, mais elles ne le sont pas.
umpirsky
9
@SalmanPK Twig n'est référencé nulle part dans le code ci-dessus. Je ne crois pas comprendre votre commentaire.
Icode4food
1
Voici un correctif pour l'essentiel précédent, cela fonctionne sous Symfony 2.1.7. gist.github.com/WishCow/5101428
K. Norbert
On dirait qu'il ya une faute de frappe $this->getFormErrorsdoit être $this->getErrorMessagesdans votre échantillon Symfony2.1
Mick
@umpirsky Pour obtenir le nom du champ, j'ai obtenu ceci: $ child-> getConfig () -> getOptions () ['label'] Il m'a
fallu une
35

Utilisez le validateur pour obtenir les erreurs pour une entité spécifique

if( $form->isValid() )
{
    // ...
}
else
{
    // get a ConstraintViolationList
    $errors = $this->get('validator')->validate( $user );

    $result = '';

    // iterate on it
    foreach( $errors as $error )
    {
        // Do stuff with:
        //   $error->getPropertyPath() : the field that caused the error
        //   $error->getMessage() : the error message
    }
}

Référence API:

Olivier 'Ölbaum' Scherler
la source
Merci, ce dont j'avais besoin +1
Phill Pafford
4
Je ne suis pas sûr que ce soit une bonne approche pour valider chaque entité séparément. Et si vous avez une forme hiérarchique complexe? Le deuxième problème est que la validation se produit deux fois.
Slava Fomin II
3
@SlavaFominII - "Le deuxième problème est que la validation se fait deux fois" - Bon point, rien ne se rafraîchit! Même liste d'erreurs après!
BentCoder
20

Pour obtenir des messages corrects (traduisibles), en utilisant actuellement SF 2.6.3, voici ma dernière fonction (car aucune de celles ci-dessus ne semble plus fonctionner):

 private function getErrorMessages(\Symfony\Component\Form\Form $form) {      
    $errors = array();
    foreach ($form->getErrors(true, false) as $error) {
        // My personnal need was to get translatable messages
        // $errors[] = $this->trans($error->current()->getMessage());
        $errors[] = $error->current()->getMessage();
    }

    return $errors;
}

car la méthode Form :: getErrors () retourne maintenant une instance de FormErrorIterator , sauf si vous changez le deuxième argument ($ flatten) sur true . (Il renverra ensuite une instance FormError , et vous devrez appeler la méthode getMessage () directement, sans la méthode current ():

 private function getErrorMessages(\Symfony\Component\Form\Form $form) {      
    $errors = array();
    foreach ($form->getErrors(true, true) as $error) {
        // My personnal need was to get translatable messages
        // $errors[] = $this->trans($error->getMessage());
        $errors[] = $error->getMessage();
    }

    return $errors;
}

)

Le plus important est en fait de définir le premier argument sur true afin d'obtenir les erreurs. Laisser le deuxième argument ($ flatten) à sa valeur par défaut ( true ) renverra des instances FormError , tandis qu'il renverra des instances FormErrorIterator lorsqu'il est défini sur false.

Cedo
la source
Nice one, utilisant le même truc.
Organique endommagé le
n'est-ce pas? :) @KidBinary
Cedo
Absolument magnifique, mec
:)
La meilleure option est: $ errors = array_map (function ($ item) {return $ item-> current () -> getMessage ();}, $ campaignForm-> getErrors (true, false));
Enrique Quero
Bonne solution pour Symfony 2.7
Yann Chabot
16

Pour mes messages flash, j'étais content $form->getErrorsAsString()

Edit (à partir de Benji_X80): Pour une utilisation SF3 $form->getErrors(true, false);

Tjorriemorrie
la source
3
Je sais que c'est une vieille réponse mais pour référence future: This method should only be used to help debug a form.( source )
cheesemacfly
getErrorsAsString () est obsolète dans la version 3.0, utilisez: $ form-> getErrors (true, false);
Benji_X80
15

La fonction pour symfony 2.1 et plus récent, sans aucune fonction obsolète:

/**
 * @param \Symfony\Component\Form\Form $form
 *
 * @return array
 */
private function getErrorMessages(\Symfony\Component\Form\Form $form)
{
    $errors = array();

    if ($form->count() > 0) {
        foreach ($form->all() as $child) {
            /**
             * @var \Symfony\Component\Form\Form $child
             */
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    } else {
        /**
         * @var \Symfony\Component\Form\FormError $error
         */
        foreach ($form->getErrors() as $key => $error) {
            $errors[] = $error->getMessage();
        }
    }

    return $errors;
}
stwe
la source
J'allais publier une nouvelle réponse à ce message, mais vous sembliez m'avoir battu au poing. J'ai dû parcourir le code source pour comprendre pourquoi les appels de méthode n'étaient pas trouvés.
Dr.Knowitall
J'ai remarqué que cela n'entraîne pas les erreurs des éléments pour lesquels la bulle d'erreur est définie sur true. SF2.4
kinghfb
@stwe quel est le but de la première IFdéclaration? Pourquoi s'exclut-il mutuellement? Autant que je sache: la forme peut avoir ses propres erreurs ainsi que des enfants.
Slava Fomin II
4

Messages d'erreur de forme traduite (Symfony2.1)

J'ai beaucoup de mal à trouver ces informations, donc je pense qu'il vaut vraiment la peine d'ajouter une note sur la traduction des erreurs de formulaire.

@Icode4foodanswer renverra toutes les erreurs d'un formulaire. Cependant, le tableau renvoyé ne prend en compte ni la pluralisation ni la traduction des messages .

Vous pouvez modifier la boucle de @Icode4foodréponse foreach pour avoir un combo:

  • Obtenez toutes les erreurs d'un formulaire particulier
  • Renvoyer une erreur traduite
  • Tenir compte de la pluralisation si nécessaire

C'est ici:

foreach ($form->getErrors() as $key => $error) {

   //If the message requires pluralization
    if($error->getMessagePluralization() !== null) {
        $errors[] = $this->container->get('translator')->transChoice(
            $error->getMessage(), 
            $error->getMessagePluralization(), 
            $error->getMessageParameters(), 
            'validators'
            );
    } 
    //Otherwise, we do a classic translation
    else {
        $errors[] = $this->container->get('translator')->trans(
            $error->getMessage(), 
            array(), 
            'validators'
            );
    }
}

Cette réponse a été élaborée à partir de 3 articles différents:

Mick
la source
J'ai juste essayé votre version et c'est parti Fatal Error: Call to undefined method Symfony\Component\Form\FormError::getMessagePluralization(). Je soupçonne que c'est pour Symfony 2.1 uniquement?
Czar Pino
4

SYMFONY 3.X

Les autres méthodes SF 3.X données ici ne fonctionnaient pas pour moi car je pouvais soumettre des données vides au formulaire (mais j'ai des contraintes NotNull / NotBlanck). Dans ce cas, la chaîne d'erreur ressemblerait à ceci:

string(282) "ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be null.
name:
    ERROR: This value should not be blank.
"

Ce qui n'est pas très utile. Alors j'ai fait ceci:

public function buildErrorArray(FormInterface $form)
{
    $errors = [];

    foreach ($form->all() as $child) {
        $errors = array_merge(
            $errors,
            $this->buildErrorArray($child)
        );
    }

    foreach ($form->getErrors() as $error) {
        $errors[$error->getCause()->getPropertyPath()] = $error->getMessage();
    }

    return $errors;
}

Ce qui rendrait cela:

array(7) {
  ["data.name"]=>
  string(31) "This value should not be blank."
  ["data.street"]=>
  string(31) "This value should not be blank."
  ["data.zipCode"]=>
  string(31) "This value should not be blank."
  ["data.city"]=>
  string(31) "This value should not be blank."
  ["data.state"]=>
  string(31) "This value should not be blank."
  ["data.countryCode"]=>
  string(31) "This value should not be blank."
  ["data.organization"]=>
  string(30) "This value should not be null."
}
sbouba
la source
3

Vous pouvez également utiliser le service de validation pour obtenir des violations de contraintes:

$errors = $this->get('validator')->validate($user);
antoinet
la source
6
Cela validera l'objet mais pas le formulaire. Si, par exemple, le jeton CRSF était la cause de l'erreur, le message ne serait pas inclus.
Icode4food
3

Messages d'erreur de forme traduite (Symfony2.3)

Ma version de la résolution du problème:

/src/Acme/MyBundle/Resources/config/services.yml

services:
    form_errors:
        class: Acme\MyBundle\Form\FormErrors

/src/Acme/MyBundle/Form/FormErrors.php

<?php
namespace Acme\MyBundle\Form;

class FormErrors
{
    public function getArray(\Symfony\Component\Form\Form $form)
    {
        return $this->getErrors($form);
    }

    private function getErrors($form)
    {
        $errors = array();

        if ($form instanceof \Symfony\Component\Form\Form) {

            // соберем ошибки элемента
            foreach ($form->getErrors() as $error) {

                $errors[] = $error->getMessage();
            }

            // пробежимся под дочерним элементам
            foreach ($form->all() as $key => $child) {
                /** @var $child \Symfony\Component\Form\Form */
                if ($err = $this->getErrors($child)) {
                    $errors[$key] = $err;
                }
            }
        }

        return $errors;
    }
}

/src/Acme/MyBundle/Controller/DefaultController.php

$form = $this->createFormBuilder($entity)->getForm();
$form_errors = $this->get('form_errors')->getArray($form);
return new JsonResponse($form_errors);

Dans Symfony 2.5, vous pouvez obtenir toutes les erreurs de champs très facilement:

    $errors = array();
    foreach ($form as $fieldName => $formField) {
        foreach ($formField->getErrors(true) as $error) {
            $errors[$fieldName] = $error->getMessage();
        }
    }
Lebnik
la source
3

Pour Symfony 3.2 et supérieur, utilisez ceci,

public function buildErrorArray(FormInterface $form)
{
    $errors = array();

    foreach ($form->getErrors() as $key => $error) {
        if ($form->isRoot()) {
            $errors['#'][] = $error->getMessage();
        } else {
            $errors[] = $error->getMessage();
        }
    }

    foreach ($form->all() as $child) {
        if (!$child->isValid()) {
            $errors[$child->getName()] = (string) $child->getErrors(true, false);
        }
    }
    return $errors;
}

Utilisez str_replace si vous voulez vous débarrasser du texte ennuyeux « Erreur: » dans chaque texte de description d'erreur.

$errors[$child->getName()] = str_replace('ERROR:', '', (string) $child->getErrors(true, false));
Anjana Silva
la source
2

Si vous utilisez des validateurs personnalisés, Symfony ne renvoie pas les erreurs générées par ces validateurs dans $form->getErrors(). $form->getErrorsAsString()renverra toutes les erreurs dont vous avez besoin, mais sa sortie est malheureusement formatée sous forme de chaîne, pas de tableau.

La méthode que vous utilisez pour obtenir toutes les erreurs (quelle que soit leur origine) dépend de la version de Symfony que vous utilisez.

La plupart des solutions suggérées impliquent la création d'une fonction récursive qui analyse tous les formulaires enfants et extrait les erreurs pertinentes dans un tableau. Symfony 2.3 n'a pas la $form->hasChildren()fonction, mais c'est le cas $form->all().

Voici une classe d'assistance pour Symfony 2.3, que vous pouvez utiliser pour extraire toutes les erreurs de n'importe quelle forme. (Il est basé sur le code d'un commentaire de yapro sur un ticket de bogue associé dans le compte github de Symfony.)

namespace MyApp\FormBundle\Helpers;

use Symfony\Component\Form\Form;

class FormErrorHelper
{
    /**
     * Work-around for bug where Symfony (2.3) does not return errors from custom validaters,
     * when you call $form->getErrors().
     * Based on code submitted in a comment here by yapro:
     * https://github.com/symfony/symfony/issues/7205
     *
     * @param Form $form
     * @return array Associative array of all errors
     */
    public function getFormErrors($form)
    {
        $errors = array();

        if ($form instanceof Form) {
            foreach ($form->getErrors() as $error) {
                $errors[] = $error->getMessage();
            }

            foreach ($form->all() as $key => $child) {
                /** @var $child Form */
                if ($err = $this->getFormErrors($child)) {
                    $errors[$key] = $err;
                }
            }
        }

        return $errors;
    }
}

Indicatif d'appel:

namespace MyApp\ABCBundle\Controller;

use MyApp\FormBundle\Helpers;

class MyController extends Controller
{
    public function XYZAction()
    {
        // Create form.

        if (!$form->isValid()) {
            $formErrorHelper = new FormErrorHelper();
            $formErrors = $formErrorHelper->getFormErrors($form);

            // Set error array into twig template here.
        }
    }

}
Jay Sheth
la source
2

Sur la base de la réponse de @Jay Seth, j'ai créé une version de la classe FormErrors spécialement pour Ajax Forms:

// src/AppBundle/Form/FormErrors.php
namespace AppBundle\Form;

class FormErrors
{

    /**
     * @param \Symfony\Component\Form\Form $form
     *
     * @return array $errors
     */
    public function getArray(\Symfony\Component\Form\Form $form)
    {
        return $this->getErrors($form, $form->getName());
    }

    /**
     * @param \Symfony\Component\Form\Form $baseForm
     * @param \Symfony\Component\Form\Form $baseFormName
     *
     * @return array $errors
     */
    private function getErrors($baseForm, $baseFormName) {
        $errors = array();
        if ($baseForm instanceof \Symfony\Component\Form\Form) {
            foreach($baseForm->getErrors() as $error) {
                $errors[] = array(
                    "mess"      => $error->getMessage(),
                    "key"       => $baseFormName
                );
            }

            foreach ($baseForm->all() as $key => $child) {
                if(($child instanceof \Symfony\Component\Form\Form)) {
                    $cErrors = $this->getErrors($child, $baseFormName . "_" . $child->getName());
                    $errors = array_merge($errors, $cErrors);
                }
            }
        }
        return $errors;
    }
}

Utilisation (par exemple dans votre action):

$errors = $this->get('form_errors')->getArray($form);

Version de Symfony: 2.8.4

Exemple de réponse JSON:

{
    "success": false,
    "errors": [{
        "mess": "error_message",
        "key": "RegistrationForm_user_firstname"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_lastname"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_email"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_zipCode"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_password_password"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_terms"
    }, {
        "mess": "error_message2",
        "key": "RegistrationForm_terms"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_marketing"
    }, {
        "mess": "error_message2",
        "key": "RegistrationForm_marketing"
    }]
}

L'objet d'erreur contient le champ "clé", qui est l'identifiant de l'élément DOM d'entrée, de sorte que vous pouvez facilement remplir les messages d'erreur.

Si vous avez des formulaires enfants dans le parent, n'oubliez pas d'ajouter l' cascade_validationoption à l'intérieur du formulaire parent setDefaults.

Voleur
la source
1

Pour Symfony 2.1 et versions ultérieures à utiliser avec l'affichage des erreurs Twig, j'ai modifié la fonction pour ajouter un FormError au lieu de simplement les récupérer, de cette façon vous avez plus de contrôle sur les erreurs et n'avez pas à utiliser error_bubbling sur chaque entrée individuelle. Si vous ne le définissez pas de la manière ci-dessous, {{form_errors (form)}} restera vide:

/**
 * @param \Symfony\Component\Form\Form $form
 *
 * @return void
 */
private function setErrorMessages(\Symfony\Component\Form\Form $form) {      

    if ($form->count() > 0) {
        foreach ($form->all() as $child) {
            if (!$child->isValid()) {
                if( isset($this->getErrorMessages($child)[0]) ) {
                    $error = new FormError( $this->getErrorMessages($child)[0] );
                    $form->addError($error);
                }
            }
        }
    }

}
Pays des merveilles durs
la source
1

$ form-> getErrors () fonctionne pour moi.

ahyong
la source
1

J'ai trouvé cette solution. Il fonctionne parfaitement avec le dernier Symfony 2.4 .

Je vais essayer de donner quelques explications.

Utilisation d'un validateur séparé

Je pense que c'est une mauvaise idée d'utiliser une validation séparée pour valider les entités et renvoyer des messages de violation de contrainte, comme suggéré par d'autres auteurs.

  1. Vous aurez besoin de valider manuellement toutes les entités, de spécifier des groupes de validation, etc.

  2. De cette façon, vous validerez le formulaire deux fois: une fois avec le formulaire et une fois avec un validateur séparé. C'est une mauvaise idée du point de vue des performances.

Je suggère d'itérer récursivement le type de formulaire avec ses enfants pour collecter les messages d'erreur.

Utilisation de certaines méthodes suggérées avec une instruction IF exclusive

Certaines réponses suggérées par d'autres auteurs contiennent des instructions IF mutuellement exclusives comme celle-ci: if ($form->count() > 0)ou if ($form->hasChildren()).

Autant que je sache, chaque formulaire peut avoir des erreurs aussi bien que des enfants. Je ne suis pas expert avec le composant Symfony Forms , mais dans la pratique, vous n'obtiendrez pas d'erreurs du formulaire lui-même, comme une erreur de protection CSRF ou des champs supplémentaires erreur de . Je suggère de supprimer cette séparation.

Utilisation de la structure de résultat dénormalisée

Certains auteurs suggèrent de mettre toutes les erreurs dans un tableau simple. Ainsi, tous les messages d'erreur du formulaire lui-même et de ses enfants seront ajoutés au même tableau avec différentes stratégies d'indexation: basé sur le nombre pour les propres erreurs du type et basé sur le nom pour les erreurs enfants. Je suggère d'utiliser la structure de données normalisée du formulaire:

errors:
    - "Self error"
    - "Another self error"

children
    - "some_child":
        errors:
            - "Children error"
            - "Another children error"

        children
            - "deeper_child":
                errors:
                    - "Children error"
                    - "Another children error"

    - "another_child":
        errors:
            - "Children error"
            - "Another children error"

De cette façon, le résultat peut être facilement réitéré plus tard.

Ma solution

Voici donc ma solution à ce problème:

use Symfony\Component\Form\Form;

/**
 * @param Form $form
 * @return array
 */
protected function getFormErrors(Form $form)
{
    $result = [];

    // No need for further processing if form is valid.
    if ($form->isValid()) {
        return $result;
    }

    // Looking for own errors.
    $errors = $form->getErrors();
    if (count($errors)) {
        $result['errors'] = [];
        foreach ($errors as $error) {
            $result['errors'][] = $error->getMessage();
        }
    }

    // Looking for invalid children and collecting errors recursively.
    if ($form->count()) {
        $childErrors = [];
        foreach ($form->all() as $child) {
            if (!$child->isValid()) {
                $childErrors[$child->getName()] = $this->getFormErrors($child);
            }
        }
        if (count($childErrors)) {
            $result['children'] = $childErrors;
        }
    }

    return $result;
}

J'espère que ça aidera quelqu'un.

Slava Fomin II
la source
@weaverryan pouvez-vous jeter un œil à ma solution s'il vous plaît? Est-ce valide, ou y a-t-il des inconvénients ou des idées fausses? Je vous remercie!
Slava Fomin II
1

SYMFONY 3.1

J'ai simplement implémenté une méthode statique pour gérer l'affichage des erreurs

static function serializeFormErrors(Form\Form $form)
{
    $errors = array();
    /**
     * @var  $key
     * @var Form\Form $child
     */
    foreach ($form->all() as $key => $child) {
        if (!$child->isValid()) {
            foreach ($child->getErrors() as $error) {
                $errors[$key] = $error->getMessage();
            }
        }
    }

    return $errors;
}

En espérant aider

Shigiang Liu
la source
1

Symfony 3 et plus récent

J'ai récemment créé une fonction qui crée un arbre d'erreurs de forme. Cela sera utile pour renvoyer la liste des erreurs au front-end. Ceci est basé sur des types de formulaires ayant:

'error_bubbling' => false

Code:

public static function getFormErrorsTree(FormInterface $form): array
{
    $errors = [];

    if (count($form->getErrors()) > 0) {
        foreach ($form->getErrors() as $error) {
            $errors[] = $error->getMessage();
        }
    } else {
        foreach ($form->all() as $child) {
            $childTree = self::getFormErrorsTree($child);

            if (count($childTree) > 0) {
                $errors[$child->getName()] = $childTree;
            }
        }
    }

    return $errors;
}

Production:

Array
(
    [name] => Array
        (
            [0] => This value is not valid.
        )

    [emails] => Array
        (
            [0] => Array
                (
                    [0] => Given e-mail is not valid.
                    [1] => Given e-mail is not valid #2.
                )
            [1] => Array
                (
                    [0] => Given e-mail is not valid.
                    [1] => Given e-mail is not valid #2.
                )

        )

)

Remarque : je sais que les erreurs des champs de niveau plus profond peuvent être écrasées si le niveau supérieur contient des erreurs, mais c'est exprès pour mon utilisation.

Krzysztof Trzos
la source
Parfait pour var_dump, merci
ReaperSoon
0

Pour Symfony 2.1:

Voici ma solution finale en rassemblant de nombreuses autres solutions:

protected function getAllFormErrorMessages($form)
{
    $retval = array();
    foreach ($form->getErrors() as $key => $error) {
        if($error->getMessagePluralization() !== null) {
            $retval['message'] = $this->get('translator')->transChoice(
                $error->getMessage(), 
                $error->getMessagePluralization(), 
                $error->getMessageParameters(), 
                'validators'
            );
        } else {
            $retval['message'] = $this->get('translator')->trans($error->getMessage(), array(), 'validators');
        }
    }
    foreach ($form->all() as $name => $child) {
        $errors = $this->getAllFormErrorMessages($child);
        if (!empty($errors)) {
           $retval[$name] = $errors; 
        }
    }
    return $retval;
}
Fernando PG
la source