Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony 2 - separate form logic, show form errors after redirect

I want to separate form validation logic:

public function contactAction()
{
    $form = $this->createForm(new ContactType());

    $request = $this->get('request');
    if ($request->isMethod('POST')) {
        $form->submit($request);
        if ($form->isValid()) {
            $mailer = $this->get('mailer');
            // .. setup a message and send it

            return $this->redirect($this->generateUrl('_demo'));
        }
    }

    return array('form' => $form->createView());
}

I want to translate into 2 separate actions:

public function contactAction()
{
    $form = $this->createForm(new ContactType());
    return array('form' => $form->createView());
}

public function contactSendAction()
{
    $form = $this->createForm(new ContactType());
    $request = $this->get('request');
    if ($request->isMethod('POST')) {
        $form->submit($request);
        if ($form->isValid()) {
            $mailer = $this->get('mailer');
            // .. setup a message and send it using 

            return $this->redirect($this->generateUrl('_demo'));
        }
    }
    // errors found - go back
    return $this->redirect($this->generateUrl('contact'));
}

The problem is that when errors exist in the form - after form validation and redirect the do NOT showed in the contactAction. (probably they already will be forgotten after redirection - errors context will be lost)

like image 671
pleerock Avatar asked Jun 24 '13 07:06

pleerock


2 Answers

If you check out how the code generated by the CRUD generator handles this you will see that a failed form validation does not return a redirect but instead uses the same view as the GET method. So in your example you would just:

return $this->render("YourBundle:Contact:contact.html.twig", array('form' => $form->createView()))

rather than return the redirect. This means you do not lose the form errors as you do in a redirect. Something else the CRUD generator adds is the Method requirement which means you could specify that the ContactSendAction requires the POST method and thus not need the extra if($request->isMethod('POST')){ statement.

You can also just return an array if you specify the template elsewhere, for example you could use the @Template annotation and then just

return array('form' => $form->createView())
like image 179
Luke Avatar answered Oct 19 '22 23:10

Luke


This seems to work for me in Symfony 2.8:

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class MyController extends Controller {
    public function templateAction()
    {
        $form = $this->createForm(new MyFormType(), $myBoundInstance);

        if ($session->has('previousRequest')) {
            $form = $this->createForm(new MyFormType());
            $form->handleRequest($session->get('previousRequest'));
            $session->remove('previousRequest');
        }

        return array(
            'form' => $form->createView(),
        );
    }

    public function processingAction(Request $request)
    {

        $form = $this->createForm(new MyFormType(), $myBoundInstance);
        $form->handleRequest($request);

        if ($form->isValid()) {
            // do some stuff
            // ...

            return redirectToNextPage();
        }

        $session->set('previousRequest', $request);

        // handle errors
        // ...

        return redirectToPreviousPage();
    }
}

Please note that redirectToNextPage and redirectToPreviousPage, as well as MyFormType, are pseudo code. You would have to replace these bits with your own logic.

like image 38
conradkleinespel Avatar answered Oct 20 '22 00:10

conradkleinespel