-- Simon R Jones <[EMAIL PROTECTED]> wrote
(on Thursday, 14 February 2008, 09:05 AM +0000):
> thanks for the reply Matthew
>
> Can I ask why _forward() stacks and only forwards at the end of the current 
> controller method? I couldn't find any reference to why it works this way 
> in the docs so when some of the guys in the office had used multiple 
> forwards (without returns) the default behaviour was confusing.

When you call _forward(), you're stayinging within the current request
cycle, but indicating you have another action to call. The way the
request cycle works is roughly as follows:

    front controller
        routing
        dispatch loop
            resolve request to controller and action
            dispatch action
                run action in controller
        send output

When you call _forward(), you're simply setting a token in the request
object; the dispatch loop checks for this token, and if set, it then
performs another iteration of the loop.

Since the setting of the token is happening within a method call, within
another method call, within yet another method call.... you can't simply
call 'continue' and have it work; you're simply in the wrong lexical
scope. Additionally, as I noted in my original reply, you can't have a
called function force the calling function to return:

    function foo() 
    {
        bar();
        print 'foo';
    }

    function bar()
    {
        return;
    }

There's simply nothing you can call in bar() that will prevent foo()
from printing 'foo'... short of a die() or exit(), and those aren't
desired in this case.

As for the manual, perhaps I can make it clearer, but it reads:

    "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."

The part that is important here is "*after* the current action is
processed" (emphasis mine) -- i.e., the new action will only be
processed after the current action is *done*.


> On 13 Feb 2008, at 19:36, Matthew Weier O'Phinney wrote:
> >
> > Correct -- you need to return. I actually usually write it as:
> >
> >    return $this-> _forward('index', 'login');
> >
> > as the return value of an action is ignored anyways.
> >
> > The reason it works this way (i.e., you need to return when forwarding)
> > is because you can't have a called function force the calling function
> > to return -- it's a language limitation.
> >
> > > Further to this, if the above is the recommended way to forward and quit
> > > the current method then this of course becomes problematic if I 
> > > abstracted
> > > the login check. I.e. if I called a function to do something like:
> > >
> > >  $this-> checkLogin();
> > >
> > > And the function checkLogin() did the necessary ACL check and also 
> > > included
> > > the forward() - to avoid DRY.
> >
> > Unfortunate, but necessary. I typically have methods like this return a
> > boolean, so I can then do something like this:
> >
> >    if (!$this-> checkLogin() {
> >        return $this-> _forward('index', 'login');
> >    }
> >
>
>

-- 
Matthew Weier O'Phinney
PHP Developer            | [EMAIL PROTECTED]
Zend - The PHP Company   | http://www.zend.com/

Reply via email to