views:

2523

answers:

5

Hello everyone,

I would like someone to explain me what _forward is exactly doing, I cannot see if _forward is also rendering the attached view to the action or just executing the action.

Also is it possible to pass argument to $this->action in a view script ?

More generally my problem is how to code a confirmation page, let's say the user input some stuff and you want to show him confirmation, is forward is mean for that case ?

Thanks

+1  A: 

My experience with Zend is limited and I hope I'm not showing you something you've already seen but according to the docs (12.7.6. Utility Methods):

_forward($action, $controller = null, $module = null, array $params = null): perform another action. If called in preDispatch(), the currently requested action will be skipped in favor of the new one. Otherwise, after the current action is processed, the action requested in _forward() will be executed.

So it sounds like the context of when it's called matters. In the latter case it will first execute the action from which it's been called then execute the forwarded action. The exception is when it's being called from the preDispatch handler

Karim
karim thanks for the answer but I have meet few case the things wasn't doing what I expect .. plus I find the doc (at least) this one kind of mysterious. also what happen if I call $this->forward and I am already in action
RageZ
+2  A: 

A part of the Framework docs I swear used to be there explained the dispatch workflow at a general level. Theres this diagram, but its awefully complicated to explain what _forward does.

When in an action _forward will set $request->isDispatched = false, and set up the request to call the controller/action specified in _forward. During postDispatch, the isDispatched is checked - if its false, the whole thing runs again using the new request.

So... If in your action you're manually rendering views, they'll still get rendered. Everything in the action will still happen, its just another action will ALSO happen afterwards.

[edit after question edit]

Forward is not meant for the response/confirm-after-post - use a redirect for that. $this->_helper->redirector->gotoUrl() etc.

Justin
That diagram image now fails.
leek
+2  A: 

_forward is an internal redirect. Where as _redirect sends a header that tells the client's browser to go to some other URL, _forward tells the Dispatcher to internally redirect the request somewhere else.

If you consider the normal dispatch order of:

 preDispatch()
 someAction()
 postDispatch()

Calling _forward at any point in that progression will cause the following steps to not be executed. So if you call _forward in preDispatch(), someAction() will not be called and so on. If you _forward() in someAction() and you are using the viewRenderer action helper to render your views (you are letting the framework choose what view script to render), then no view script will be rendered in someAction().

When the request is forwarded to the new Controller / Module the entire dispatch process will be repeated there.

You can find out what action is being dispatched by using:

 $action = $this->getRequest()->getParam('action');

$action will be the url form of the action so if the method is name 'someKindOfAction', $action will contain 'some-kind-of'. You can do this as well for controllers and modules.

smack0007
+2  A: 

Forward is ment to be used when external redirect is not the right options. Use case (bit ankward, but best i can make up): You have a form that can add your pet (either dog or cat). You have different models for each. You include a select in your form to select dog / cat. Then in your action you do:

if($form->isValid($_POST)){  
  switch($form->select->getValue()){
    case "dog":
      $this->_forward('add-dog','pets','default');
      break;
    case "cat":
      $this->_forward('add-cat','pets','default');
      break;    
  }
}

And you handle different things for cats and dogs in separate actions. The advantage of this is that ALL the parameters are sent along. In constrast when you'd used $this->_redirect() the POST parameters will be lost. That is in some cases intended behaviour (for example after adding a comment you make a redirect to comments list page to avoid double posts and the message "page needs to send data again...".

Tomáš Fejfar
+1  A: 

I think it's important to note that _forward is very inefficient, and you should always call your method directly. When you do a _forward, the init(), pre and post dispatch run again. Depending on what you have in your init, you can run (and insert) the same database record twice.

It is easy to use but wasteful. If you profile your code, and are banging your head to why everything is being called twice, _forward is the reason. If your like me and you instantiate a few objects in the init() for use throughout the class, you wind up instantiating everything twice! I did load testing on my code and I got better performance by calling the action name directly, like foo(), instead of _forward('foo');

Another off topic tip I think most people know, is it use single quotes wherever possible, sine the PHP parser has to check a string for embedded variables. I don't know how much real world performance this will give, especially if you are using an opcode cache, but it's a best practice.

Dan
I see your point with dispatch ran again, the only things when you want to forward in same controller calling the method directly is better, but when it is a different controller you probably have to initialize lot of stuff by hand i.e. `$this->_request`
RageZ
and in my case I use that also for login check purpose, i.e that page your should authenticated but you are not so show the login page ... and my login/logout code is always in a separate controller (in most case)
RageZ
Dan, I believe your statement is partially incorrect: "When you do a _forward, the init(), pre and post dispatch run again. Depending on what you have in your init, you can run (and insert) the same database record twice."Actually, init is called only once, in the consructor...the pre and post dispatch are called multiple times though.
joedevon