Zend Framework: Post to different action then retu

2019-07-14 17:10发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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().



回答4:

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.