Symfony 2 - отдельная логика формы, ошибки отображения формы после перенаправления

Я хочу разделить логику проверки формы:

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());
}

Я хочу перевести на два отдельных действия:

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'));
}

Проблема заключается в том, что когда ошибки существуют в форме - после проверки формы и перенаправления НЕ отображаются в contactAction. (возможно, они уже будут забыты после перенаправления - ошибки будут потеряны)

Ответ 1

Если вы посмотрите, как обрабатывает код, генерируемый генератором CRA , вы увидите, что неудачная проверка формы не возвращает перенаправление, но вместо этого использует тот же вид как метод GET. Поэтому в вашем примере вы просто:

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

а не вернуть перенаправление. Это означает, что вы не потеряете ошибки формы, как в случае перенаправления. Что-то еще, что добавляет генератор CRUD, это Требование к методу, что означает, что вы можете указать, что для ContactSendAction требуется метод POST и, следовательно, не нужен дополнительный оператор if($request->isMethod('POST')){.

Вы также можете просто вернуть массив, если вы укажете шаблон в другом месте, например, вы можете использовать аннотацию @Template, а затем просто

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

Ответ 2

Это похоже на работу в 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();
    }
}

Обратите внимание, что redirectToNextPage и redirectToPreviousPage, а также MyFormType, являются псевдокодом. Вам придется заменить эти биты своей собственной логикой.