Zend Framework generally avoids telling you how to do things, prefering to give ways to achiving what you want, but avoiding making reccomendations. That can be a weakness as well as a strength.
If two forms are on one page, submitting to the same action that rendered the page, both will try and validate which looks a bit odd from user point of view and could potentialy cause application problems.
To avoid this, I decided to have each form submit to it’s own action. This kept the main page rendering action nice and neat, separating the other logic out nicely.
public function trackAction(){
$form = $this->_getCompletionForm();
$form->setAction( $this->getRequest()->getBaseUrl() . '/task/complete/task/' . $task);
# Add form to view
$this->view->formComplete = $form;
$form = $this->_getCommentForm();
$form->setAction( $this->getRequest()->getBaseUrl() . '/task/addcomment/task/' . $task);
# Add form to view
$this->view->form = $form;
}
and then the actions to proccess the forms:
public function addcommentAction(){
$task = $this->_getParam('task');
$form = $this->_getCommentForm();
$request = $this->getRequest();
if ($this->getRequest()->isPost() and $form->isValid($request->getPost())) {
// save comment
$redirector = $this->_helper->getHelper('Redirector');
$redirector->gotoSimple("track", "task",null, array('mig' => $migration))
}else{
return $this->_forward('track'); // re-render the login form
}
}
and again for the complete task form
public function completeAction(){
$form = $this->_getCompletionForm();
$request = $this->getRequest();
if ($this->getRequest()->isPost() and $_POST['check'] = 'yep' and $form->isValid($request->getPost())) {
/// save the information
return $this->_helper->redirector('index');
}else{
return $this->_forward('track'); // re-render the login form
}
}
So far, so good. The forms will not show any validation however, because a new instance of the controller is created when the _forward method is used.
To get round this last hurdle, we need to persist the forms in the registry. so, the get form methods look like this:
private function _getCommentForm(){
if (!Zend_Registry::isRegistered('form_contact')){
require_once (APPLICATION_PATH . '/forms/comment.php');
$this->_commentForm = new Form_Comment();
Zend_Registry::set('form_contact', $this->_commentForm);
}else{
$this->_commentForm = Zend_Registry::get('form_contact');
}
return $this->_commentForm;
}
private function _getCompletionForm(){
if (!Zend_Registry::isRegistered('form_complete')){
require_once (APPLICATION_PATH . '/admin/forms/Completion.php');
$this->_completeForm = new Form_Completion();
Zend_Registry::set('form_complete', $this->_completeForm);
}else{
$this->_completeForm = Zend_Registry::get('form_complete');
}
return $this->_completeForm;
}
And that’s it! The forms submit to their own actions, forward back if not valid and display any errors (because they are the same form object, it knows to display the errors).
Refrences
http://framework.zend.com/manual/en/zend.registry.html






You solution above works well but how about we simplify the process a bit. How do you feel about this?
Back in the day we use to just put hidden fields in our form and check if it “isset’ when it comes time to process the form. How about just adding a hidden field in your form e.g
//form process flag in case multiple forms$process = new Zend_Form_Element_Hidden ( 'process_signup' );
$process->setValue(true);
then check it in the controller to make sure it exists..e.g
//try to grab the form data
@$formData = $this->getRequest ()->getPost ();
if ($this->getRequest ()->isPost () && isset($formData['process_signup'])) {...only do all the validation and processing here..}
That way forms can co-exist without a lot of back and forth processing and messing with the registry.
What are your arguments against this method?
Very good. Thank you both. Dwamian Mcleish, you have just forgotten to add your hidden element :
$this->addElements(array($process));
Otherwise it works very well.
It’s Just I need it. I’d also this problem.
But it’s very nice. Forms are working.
Thanks to Dwamian Mcleish.
I wanted the same controller/action, but my solution was to make one more route structure and put in a extra param:
domain.com/controller/action/action2
And to pick up that forms action just if action2 == “thisformsparam”