Zend Framework: Post to different action then return to original action if fails validation AND keep form fields

StackOverflow https://stackoverflow.com/questions/3876877

Question

This might sound like an odd scenario, but I've got two forms on one page. One is just posting back to itself. I made the second post to another action to keep the code cleaner. Maybe not the right choice...

The problem I'm having now is that if that second form doesn't validate, I redirect back to the page with the form but I don't know how to keep my form fields filled in with the original information the user entered. Is there a way to do that and keep posting to two separate actions, or do I need to just bite the bullet and have both forms post back to the same action and deal with the messy logic?

Was it helpful?

Solution

I would submit both forms to the same action. There really shouldn't be anything too messy about it. In each form include a hidden field to signify which form is being submitted.

Application_Form_Login:

 /* other form elements */
 $this->addElement('hidden', 'login', array(
      'value' => 1
 ));

Application_Form_Register:

 /* other form elements */
 $this->addElement('hidden', 'register', array(
      'value' => 1
 ));

Controller:

$loginForm = new Application_Form_Login();
$registerForm = new Application_Form_Register();

if($this->_request->isPost()) {
     if($this->_request->getPost('login')) {
         if($loginForm->isValid($this->_request->getPost())) {
             // validated, redirect
             $this->_helper->redirector('profile', 'user');
         }
     }
     if($this->_request->getPost('register')) {
         if($registerForm->isValid($this->_request->getPost())) {
             // validated, proceed as needed
         }
     }
}

$this->view->loginForm = $loginForm;
$this->view->registerForm = $registerForm;

View:

echo $this->loginForm;

echo $this->registerForm;

With this type of a setup, if either of your forms fail validation, isValid() will preserve any data that has been entered and you still redirect on a successful validation of one or both of the forms.

OTHER TIPS

Personally, I think that each form should post to its own controller, as you have. This keeps the code for processing that form in a single place. The issue here is that you want to return to the original page on failed validation. But why? Why not simply redisplay the form in the target controller, just like you would if there were a single form on the page?

For example, consider a login form that appears on every page of a sie (perhaps because it in the site template/layout). It posts to something like AuthController::loginAction(). If the login fails, then you don't typically send him back to the page from which he came. You leave him at the login page, with the form as pre-filled from the $_POST as you want it to be (probably a username, but not his password).

See this answer for a similar discussion.

Update: Had another thought in this. If you really want to handle the processing in two different controllers in order to keep him on the page from which he posted the form, at least extract that form processing out into an action helper. This way, you could at least keep that form-processing DRY.

Update: Rob Allen has just written a great blog post "A form in your layout" in which he describes a method that uses an action-helper with a preDispatch() method that instantiates and processes the form. Very nice.

How do you redirect? I don't see the problem if you just display the form page again. You can prefill you forms using Zend_Form::populate().

Well, I would just keep both forms submitting on the same page.

I don't see why your code should get any less readable. Learn how to use action helpers and your controllers will suddenly look extremely simple and readable:

public function indexAction() 
{
    $request = $this->getRequest();

    // send forms to view, so we can print them
    // but also so we can access them in action helpers
    $this->view->form = $this->_getForm('Form1', '/');
    $this->view->form2 = $this->_getForm('Form2', '/');

    if ($request->isPost())
    {
        // process the first form
        if (isset($_POST['form_submit_button']) && $this->view->form->isValid($_POST))
        {
            $this->_helper->form($this->view->form->getValues());
        }
        // process the second form
        else if (isset($_POST['form2_submit_button']) && $this->view->form2->isValid($_POST))
        {
            $this->_helper->form2($this->view->form2->getValues());
        }
}

Each form's processing would have its own action helper.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top