Frage Symfony2 "Dieses Formular sollte keine zusätzlichen Felder enthalten" Fehler bei Sammlungen und dynamischem Feld


Also, in Tag 5 der Fehlersuche gehen und es immer noch nicht schaffen. Ich habe sogar ein spezielles Formular nur für die Fehlersuche erstellt, konnte aber noch keine Fortschritte machen. Grundproblem: Ich habe ein Symfony2-Formular, das über FormBuilderInterface mithilfe von Formularmodifikatoren erstellt wurde, um ein Feld basierend auf der Benutzerauswahl der ersten Entität im Formular dynamisch zu füllen. Das Formular enthält auch 3 Sammlungen (die One-to-One-Assoziationen mit der Hauptklasse des Formulars darstellen).

Egal was ich mache, weiter if ($form->isValid()) Ich bekomme das nur allzu vertraute und lustige "FEHLER: Dieses Formular sollte keine zusätzlichen Felder enthalten." Fehler bei der Einreichung des Formulars (3 Mal, 1 für jede Sammlung).

Bemerkenswert und wahrscheinlich mit dem Fix verbunden: Wenn ich die Collection-Entitäten aus dem Formular entferne, wird sie korrekt validiert. Mit jeder der Sammlungen im Formular oder einer beliebigen Kombination von zwei der drei Sammlungen (ich habe alles versucht), löst es den Fehler "Dieses Formular sollte keine zusätzlichen Felder enthalten" aus.

Hier ist der Code für den Formulartyp:

class ThisDataClassType extends AbstractType
{

protected $user_id;

public function __construct($user_id) {
    $this->user_id = $user_id;
}

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{

    $user_id = $this->user_id;

    $builder->add('firstChoice', 'entity', array(
            'class' => 'MyBundle:FirstChoice',
            'query_builder' => function(firstChoiceRepository $repository) use ($user_id) {
                    return $repository->createQueryBuilder('f')
                        ->where('f.user = ?1')
                        ->andWhere('f.isActive = 1')
                        ->setParameter(1, $user_id);
                },
            'property' => 'firstChoice_name',
            'required' => true,
            'mapped' => false,
            'label' => 'block.firstChoice.name'
        ))
        ->add('sub_block_name','text', array(
            'label' => 'subblock.block.name',
            'max_length' => 50,
            'required' => true,
            'attr' => array(
                'placeholder' => 'subblock.phv.name',
                'pattern' => 'alpha_numeric'
            )
        ))

        // ... bunch of other standard form types (text, etc.) ... //

        ->add('subdata1', 'collection', array(
            'type' => new SubData1Type()
        ))
        ->add('subdata2', 'collection', array(
            'type' => new SubData2Type()
        ))
        ->add('subdata3', 'collection', array(
            'type' => new SubData3Type()
        ));

    $formModifier = function(FormInterface $form, $firstChoice_id) {

        $form->add('secondChoice', 'entity', array(
            'class'         => 'MyBundle:SecondChoice',
            'query_builder' => function(secondChoiceRepository $S_repository) use ($firstChoice_id) {
            return $S_repository->createQueryBuilder('s')
                ->where('s.firstChoice_id = ?1')
                ->andWhere('s.isActive = 1')
                ->setParameter(1, $firstChoice_id);
            },
            'property'    => 'secondChoice_name',
            'label'       => 'block.secondChoice.name'
        ));
    };

    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function(FormEvent $event) use ($formModifier) {
            $data = $event->getData()->getId();
            $formModifier($event->getForm(), $data);
        }
    );

    $builder->get('firstChoice')->addEventListener(
        FormEvents::POST_SUBMIT,
        function(FormEvent $event) use ($formModifier) {
            $data = $event->getForm()->getData();
            $formModifier($event->getForm()->getParent(), $data->getId());
        }
    );

    $builder->setMethod('POST');
}

/**
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'MyBundle\Entity\ThisDataClass',
        'user_id' => null,
        'translation_domain' => 'block',
        'cascade_validation' => true
    ));
}

/**
 * @return string
 */
public function getName()
{
    return 'ThisDataForm';
}
}

... und der Basis-Controller (gerade zum Testen verwendet):

public function TestFormAction(Request $request, $whichSize)
{
    $user_id = $this->getUser()->getId();
    $success = 'Not submitted';

    $dataclass = new Entity\ThisDataClass();
    $subdata1 = new Entity\SubData1();
    $subdata2 = new Entity\SubData2();
    $subdata3 = new Entity\SubData3();

    if (!$request->isMethod('POST')) {
        $dataclass->getSubData1()->add($subdata1);
        $dataclass->getSubData2()->add($subdata2);
        $dataclass->getSubData3()->add($subdata3);
    }

    $form = $this->createForm(new Form\ThisDataClassType($user_id), $dataclass, array(
        'action' => $this->generateUrl('my_custom_test_route', array('whichSize' => $whichSize)),
        'user_id' => $user_id
    ));

    $form->handleRequest($request);

    if ($form->isValid()) {
        $success = 'Success!!';
        return $this->render('MyBundle:DataClassTestForm.html.twig', array('dataClassTestForm' => $form->createView(), 'whichSize' => $whichSize, 'success' => $success));

    } else {
        $success = $form->getErrorsAsString();
    }

        return $this->render('MyBundle:DataClassTestForm.html.twig', array('dataClassTestForm' => $form->createView(), 'whichSize' => $whichSize, 'success' => $success));

}

Um ein paar andere wichtige Punkte zu nennen:

  • das Formular wird korrekt angezeigt (alle Entitäten zeigen korrekte Werte und werden wie gewünscht aktualisiert)
  • alle erwarteten POST-Variablen befinden sich in den Post-Daten (geprüft über Firebug und Symfony's Profiler)
  • Es gibt keine zusätzlichen Variablen in den Post - Daten, die nicht auf die Klassen (außer für das Feld firstChoice mit 'mapped' => false einstellen, und das CSRF _token, aber ich bekomme den Fehler, ob ich das CSRF _token explizit aktiviere oder nicht, und wieder verschwindet der Fehler, wenn ich die Sammlungen entferne)

Ich schätze jeden Einblick, was ich vermisse.


6
2018-03-29 14:12


Ursprung


Antworten:


Nachdem ich eineinhalb Tage frei genommen hatte und weg war, knallte die Antwort, als ich mich hinsetzte und ziemlich offensichtlich war. Der beschriebene Controller fügt die Subdataklassen nur dann dem Formular hinzu, wenn es zum ersten Mal erstellt wird (dh wenn kein Sende- / POST-Ereignis aufgetreten ist). Daher enthält das nach dem submit-Ereignis erstellte Formular alle Post-Daten, aber die Klassen sind nicht damit verknüpft. Der Controller wurde nun wie folgt umgeschrieben und das Formular wird jetzt wie erwartet validiert:

public function TestFormAction(Request $request, $whichSize)
{
    $user_id = $this->getUser()->getId();
    $success = 'Not submitted';

    $dataclass = new Entity\ThisDataClass();
    $subdata1 = new Entity\SubData1();
    $subdata2 = new Entity\SubData2();
    $subdata3 = new Entity\SubData3();
    $dataclass->getSubData1()->add($subdata1);
    $dataclass->getSubData2()->add($subdata2);
    $dataclass->getSubData3()->add($subdata3);

    $form = $this->createForm(new Form\ThisDataClassType($user_id), $dataclass, array(
        'action' => $this->generateUrl('my_custom_test_route', array('whichSize' => $whichSize)),
        'user_id' => $user_id
    ));

    $form->handleRequest($request);

    if ($form->isValid()) {
        $success = 'Success!!';
    } else {
        $success = 'Invalid!!';
    }

} // RESULT::Success!!

8
2018-03-30 21:31