2014-12-23 9 views
5

Używam Symfony 2 i mam formularz, na którym umieszczam adnotacje @Assert \ NotBlank(). Jestem volontarily wypełniając pola, mój formularz nie przechodzi testu isValid i isSubmitted i po tych wierszach otrzymuję wartość inną niż null dla wyjścia (var_dump ($ recipeForm-> getErrors()));symfony2: błędy formowania nie są wyświetlane w gałązce mimo niezerowego getErrorsAsString()

private 'errors' => 
    array (size=4) 
     0 => 
     object(Symfony\Component\Form\FormError)[4119] 
      private 'message' => string 'Cette valeur doit être vide.' (length=29) 
      protected 'messageTemplate' => string 'This value should be blank.' (length=27) 
      protected 'messageParameters' => 
      array (size=1) 
       ... 
      protected 'messagePluralization' => null 
      private 'cause' => 
      object(Symfony\Component\Validator\ConstraintViolation)[4062] 
       ... 
      private 'origin' => null 

W moim szablonie gałązkowym renderuję formularz za pomocą prostego formularza (formularza). form_errors (form) lub form_errors (form.field) nie wyrenderuje błędów. Czemu? Dlaczego mogę zrobić, aby lepiej zrozumieć, skąd bierze się ten problem?

Mam dość skomplikowany typ. w przypadku niektórych innych form mojej witryny błędy są poprawnie wyświetlane. Mój typ:

<?php 
//src/AppBundle/Form/FoodAnalytics/RecipeType.php 
namespace AppBundle\Form\FoodAnalytics; 

use AppBundle\Form\Core\MediaType; 
use AppBundle\Repository\FoodAnalytics\UnitRepository; 
use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class RecipeType extends AbstractType 
{ 
    protected $recipeIngredientQueryBuilder; 
    protected $recipeSubrecipeQueryBuilder; 
    protected $unitRepository; 
    protected $action; 

    /** 
    * @return string 
    */ 
    public function getName() 
    { 
     return 'appbundle_foodanalytics_recipe' . $this->action; 
    } 

    public function __construct(UnitRepository $unitRepository, $recipeIngredientQueryBuilder=null, $recipeSubrecipeQueryBuilder=null, $action = null) 
    { 
     $this->recipeIngredientQueryBuilder = $recipeIngredientQueryBuilder; 
     $this->recipeSubrecipeQueryBuilder = $recipeSubrecipeQueryBuilder; 
     $this->unitRepository = $unitRepository; 
     $this->action = $action == null ? null : '_' . $action; 
    } 

    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('recipeCategories', 'genemu_jqueryselect2_entity',array(
        'multiple' => true, 
        'class' => 'AppBundle:FoodAnalytics\RecipeCategory', 
        'label' => 'Catégories', 
        'required' => false, 
        'by_reference' => false, 
        'attr'=>array(
         'data-toggle'=>"tooltip", 
         'data-placement'=>"top", 
         'title'=>"Indiquez les catégories dans lesquelles enregistrer la recette pour un recherche future plus facile", 
        ))) 
      ->add('isProduct', null, array(
        'label'=>'Correspond à un produit fini', 
        'required'=>false, 
        'attr'=>array(
         'data-toggle'=>"tooltip", 
         'data-placement'=>"top", 
         'title'=>"La recette correspond-elle à un produit fini qui peut être mis en vente ?", 
        ))) 
      ->add('name', null, array(
        'label'=>'Nom détaillé', 
        'attr'=>array(
         'data-toggle'=>"tooltip", 
         'data-placement'=>"top", 
         'title'=>"Indiquez le nom détaillé de la recette. Par exemple : 'millefeuilles praliné ganache vanille sur feuilletage inversé'", 
        ))) 
      ->add('nickName', null, array(
        'label'=>'Nom raccourci', 
        'attr'=>array(
         'data-toggle'=>"tooltip", 
         'data-placement'=>"top", 
         'title'=>"Indiquez un nom raccourci pour la recette. Par exemple : 'millefeuilles'", 
        ))) 
      ->add('recipeIngredients', 'collection', array(
        'type' => new RecipeIngredientType($this->unitRepository, $this->recipeIngredientQueryBuilder), 
        'by_reference' => false, 
        'label'=>'Ingrédient', 
        'allow_add' => true, 
        'allow_delete' => true, 
        'cascade_validation' => true, 
       )) 
      ->add('subrecipes', 'collection', array(
        'type' => new RecipeSubrecipeType($this->unitRepository, $this->recipeSubrecipeQueryBuilder), 
        'by_reference' => false, 
        'label'=>'Sous-recette', 
        'allow_add' => true, 
        'allow_delete' => true 
       )) 
      ->add('recipeSteps', 'collection', array(
        'type' => new RecipeStepType(), 
        'by_reference' => false, 
        'label'=>'Etape de production', 
        'allow_add' => true, 
        'allow_delete' => true 
       )) 
      ->add('portions', null, array(
        'label'=>'Nombre de parts/de pièces', 
        'required' => false, 
        'attr'=>array(
         'data-toggle'=>"tooltip", 
         'data-placement'=>"top", 
         'title'=>"Indiquez le nombre d'éléments disponibles dans la recette. Cela peut permettre d'utiliser l'unité 'U' dans les recettes parentes qui l'utiliseront", 
        ))) 
      ->add('shortDescription', null, array(
        'label'=>'Description courte', 
        'required'=>false, 
        'attr'=>array(
         'data-toggle'=>"tooltip", 
         'data-placement'=>"top", 
         'title'=>"Décrivez succinctement la recette", 
        ))) 
      ->add('medias', 'collection', array(
        'type' => new MediaType(), 
        'by_reference' => false, 
        'label'=>'Medias', 
        'allow_add' => true, 
        'allow_delete' => true, 
        'required' => false, 
        'attr'=>array(
         'data-toggle'=>"tooltip", 
         'data-placement'=>"top", 
         'title'=>"Ajoutez des images ou vidéos pour décrire la recette", 
        ))) 
      ->add('content', 'textarea', array(
        'label'=>'Instructions générales', 
        'required'=>false, 
        'attr' => array(
         'data-toggle'=>"tooltip", 
         'data-placement'=>"top", 
         'class' => 'summernote', 
         'title'=>"Ajoutez du contenu supplémentaire pour détailler la recette", 
        ))) 
      ->add('workingDuration', 'timepicker', array(
         'label'=>'Temps total de travail', 
         'required' => false, 
         'attr'=>array 
         (
          'class' => 'timepicker', 
          'data-toggle'=>"tooltip", 
          'data-placement'=>"top", 
          'title'=>"Indiquez le temps total de travail consacré à la recette si il diffère du temps de travail cumulé des étapes de production", 
         ))) 
      ->add('sleepDuration', 'timepicker', array(
        'label'=>'Temps total de repos', 
        'required' => false, 
        'attr'=>array 
        (
         'data-toggle'=>"tooltip", 
         'class'=>'timepicker', 
         'data-placement'=>"top", 
         'title'=>"Indiquez le temps total de repos consacré à la recette si il diffère du temps de repos cumulé des étapes de production", 
        ))) 
     ; 
    } 

    /** 
    * @param OptionsResolverInterface $resolver 
    */ 
    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\FoodAnalytics\Recipe', 
//   'cascade_validation' => true, 
     )); 
    } 
} 

EDIT: utrzymanie tylko jednego prostego pola tego formularza niczego nie zmienia, błąd nie zostanie pokazany

Odpowiedz

0

Wydaje się, że błąd jest spowodowany przez regułę walidacji na nieruchomości to część twojej jednostki Recipe, ale nie została dodana do RecipeType, więc błąd nie może być powiązany z żadnym z podformuł.

Spróbuj sprawdzić swoją jednostkę i dowiedzieć się, jakie obiekt ma reguły walidacji i nie dodaje się do RecipeType albo dodać wartość domyślną dla tej nieruchomości lub użyj Validation Groups

+0

Cóż, błąd jest w rzeczywistości spowodowany przez pole dodane do rodzaju receptury i wiem, który z nich nieprawidłowo pole to źle. Form-> geterrorsasstring wyświetla odpowiedni błąd, ale nie szablon gałązki, to jest ta dziwna część. –

6

Spójrz jak błędy są renderowane tutaj: http://symfony.com/doc/current/cookbook/form/form_customization.html#customizing-error-output

Problem z używaniem {{ form_errors(form) }} polega na tym, że wyświetla błędy w postaci błędów globalnych, a nie pojedynczych, podczas gdy getErrorsAsString() przejdzie przez wszystkie pola. Jeśli chcesz, aby wszystkie pojedyncze błędy w polu były dostępne przez {{ form_errors(form) }}, musisz edytować każde pole w formularzu i dodać opcję error_bubbling => true.

Jeśli nie ustawisz propagacji błędów na wartość true we wszystkich naszych polach, musisz wyrenderować błąd każdego pola osobno - na przykład: {{ form_errors(form.name) }} lub po prostu użyć {{ form_row(form.name) }}, który renderuje etykietę, element formularza i błędy w jednym ujęciu.

+1

Niestety, error_bubbling => true nie działa. Jeśli renderuję formularz z formularzem (formularz) lub form_errors (form.field) lub form_row (form.field), nic się nie zmienia. Mam również pusty zrzut dla tych wartości, podczas gdy getErrorsAsString nie jest pusty. Niektóre inne formularze na mojej stronie działają prawidłowo ... Czy wiesz, jak śledzić błędy od miejsca, w którym zostały przyciągnięte do miejsca, w którym są wyświetlane? Myślę, że potrzebuję dodatkowych trików do debugowania ... –

+0

Czy upewniłeś się, że wstawiłeś 'error_bubbling => true' na każdym polu? Kiedy zaczynałem od formularzy Symfony, myślałem, że mogę ustawić tę opcję dla całego formularza, ale tak nie jest. Musi to być na pole. Być może mógłbyś opublikować konfigurację, w której dodałeś bulgotanie błędów, a także swój kod Twig do wyświetlania formularza? –

+0

cóż, jeśli wstawię error_bubbling na nickname, a także wstawię Assert \ NotBlank(), po prostu otrzymam to samo: brak błędów, ale widzę błąd w getErrorsAsString. Dodam prostszy przykład błędu formy, aby go zawęzić. –

3

Ah my God!

Przykro mi, że ludzie stracili czas z tym! Problem polegał na tym, że przekazywałem jako odpowiedź tablicę $response = array(form->createView()), ale odpowiedź tablicy została wygenerowana, zanim obsłużę żądanie. Dlatego też mogłem zobaczyć go w gnieździe, a nie w gałązce.

+1

To prawie zawsze coś prostego. Cieszę się, że to wymyśliliście. –