简体   繁体   中英

Extra fields at Symfony2 form, how to avoid them or fix this issue?

I have OrdersType.php Symfony2 Form with this code:

class OrdersType extends AbstractType {

    /**
     * @var string
     */
    protected $register_type;

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

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('nickname', 'text', array(
                    'required' => FALSE,
                    'label' => "Nickname/Seudónimo",
                    'trim' => TRUE,
                    'attr' => array(
                        'class' => 'nickname'
                    )
                ))
                ->add('email', 'email', array(
                    'required' => TRUE,
                    'label' => "Correo Electrónico",
                    'trim' => TRUE
                ))
                ->add('phone', 'text', array(
                    'required' => TRUE,
                    'label' => 'Números de teléfono (separados por "/")',
                    'trim' => TRUE
                ))
                ->add('fiscal_address', 'textarea', array(
                    'required' => TRUE,
                    'label' => 'Dirección'
                ))
                ->add('shipping_address', 'textarea', array(
                    'required' => TRUE,
                    'label' => 'Dirección de Envío'
                ))
                ->add('shipping_from', 'choice', array(
                    'label' => 'Compañía de Encomiendas',
                    'choices' => SFType::getChoices()
                ))
                ->add('payment_type', 'entity', array(
                    'class' => 'CommonBundle:PaymentType',
                    'property' => 'name',
                    'required' => TRUE,
                    'label' => 'Forma de Pago',
                    'empty_value' => '-- SELECCIONAR --'
                ))
                ->add('order_amount', 'number', array(
                    'label' => 'Monto',
                    'required' => TRUE,
                    'precision' => 2
                ))
                ->add('bank', 'entity', array(
                    'class' => 'CommonBundle:Bank',
                    'property' => 'name',
                    'required' => TRUE,
                    'label' => 'Banco',
                    'empty_value' => '-- SELECCIONAR --'
                ))
                ->add('transaction', 'text', array(
                    'required' => TRUE,
                    'label' => 'No. Transacción'
                ))
                ->add('comments', 'textarea', array(
                    'required' => FALSE,
                    'label' => 'Comentarios'
                ))
                ->add('secure', 'checkbox', array(
                    'label' => FALSE,
                    'required' => FALSE,
                    'value' => 1,
                    'mapped' => FALSE
                ))
                ->add('suscribe_mail_list', 'checkbox', array(
                    'label' => FALSE,
                    'required' => FALSE,
                    'value' => 1,
                    'mapped' => FALSE
        ));

        if ($this->register_type[0] == "natural")
        {
            $builder->add('nat', new NaturalPersonType(), array(
                'mapped' => FALSE
            ));
        }
        elseif ($this->register_type[0] == "legal")
        {
            $builder->add('leg', new LegalPersonType(), array(
                'mapped' => FALSE
            ));
        }
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Tanane\FrontendBundle\Entity\Orders',
            'render_fieldset' => FALSE,
            'show_legend' => FALSE,
            'intention' => 'orders_form'
        ));
    }

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

Then at controller I have this:

public function saveAction(Request $request)
{
    $orders = $request->get('orders');
    $sameAddress = $request->get('same_address');

    ladybug_dump($orders);

    // NaturalPerson: 1 | LegalPerson: 2
    $person_type = $orders['nat'] ? 1 : 2;
    $register_type = $orders['nat'] ? array("nat") : array("leg");

    $entityOrder = new Orders();
    $formOrder = $this->createForm(new OrdersType($register_type), $entityOrder);

    $formOrder->handleRequest($request);

    $em = $this->getDoctrine()->getManager();
    $em->getConnection()->beginTransaction();

    if ($formOrder->isValid())
    {
        ....
    }
    else
    {
        $errors = $this->getFormErrors($formOrder);
    }

    return $this->render('FrontendBundle:Site:process.html.twig', array('message' => $message));
}

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

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

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

    return $errors;
}

When I send the form it fails with this message:

This form should not contain extra fields

But I can't see where is the problematic field that's being added to the form, how can I see it? Any advice around this common issue?

1st test

Although I do not need a collection of forms I followed the instructions at this doc and I rewrite the form as follow:

    if ($this->register_type[0] == "natural")
    {
        $builder->add('nat', 'collection', array(
            'type' => new NaturalPersonType(),
            'mapped' => FALSE
        ));
    }
    elseif ($this->register_type[0] == "legal")
    {
        $builder->add('leg', 'collection', array(
            'type' => new LegalPersonType(),
            'mapped' => FALSE
        ));
    }

In this way the main error about extra fields is gone but now I'm not able to render the field. I'm doing as follow:

{% for item in orderForm.nat %}
    {{ form_widget(item.description, {'attr':{'class':'form-control'}})}}
{% endfor %}

But this does not render any field. Why?

after binding of post data to form in your controller:

$form->handleRequest

check value of:

$form->getExtraData();

there should be extra fields

Finally I got where the error was. The issue is not related to mapped=>false but because I was sending other values, totally different, ​​when creating and processing the form in the method that handles the information persist. See the code below where I fix the issue:

Function that creates the form at Controller

public function orderAction($type)
{
    $order = new Orders();
    $orderForm = $this->createForm(new OrdersType(array($type)), $order, array('action' => $this->generateUrl('save_order')));

    $template = $type === "natural" ? "FrontendBundle:Natural:natural.html.twig" : "FrontendBundle:Legal:legal.html.twig";
    return $this->render($template, array('order' => $order, "orderForm" => $orderForm->createView()));
}

BEFORE

public function saveAction(Request $request)
{
    $orders = $request->get('orders');
    $sameAddress = $request->get('same_address');

    $register_type = $orders['nat'] ? array("nat") : array("leg");
    $entityOrder = new Orders();
    $formOrder = $this->createForm(new OrdersType($register_type), $entityOrder);

    ...

}

AFTER

public function saveAction(Request $request)
{
    $orders = $request->get('orders');
    $sameAddress = $request->get('same_address');

    $register_type = $orders['nat'] ? array("natural") : array("legal"); // this line fixes the error

    $entityOrder = new Orders();
    $formOrder = $this->createForm(new OrdersType($register_type), $entityOrder);

    ...

}

Problem solved, thanks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM