We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Stopping the forward flow and the redirection problem

I check permissions in onConstruct method and want to stop any action execution if access is denied, but to render standard layout as usual. If possible not redirecting to another page. Why, i write below. How to do the stop.

There is $this->response->redirect('authentication/accessdenied'); which i want to use to redirect to a page with user friendly information. If i must use response->redirect i've noticed a problem. The problem is after the execution of the redirect method i had been able to do some php instructions before redirect actually worked. In my case php die() function worked faster. Not sure whether this can cause some insesure stuff/instructions to be executed in this time gap.

I know there is _finish property in the dispatcher object. I understand i cannot change it to stop the controller flow

There is as i remember an beforeExecuteRoute what i couldn't use returning true or false to stop the flow or not, yet the method/event generally works.



9.8k
Accepted
answer
edited Feb '15

Ok, i've possibly found a good way to resolve the problem avoiding using the redirection. Yet i might not know about some things, but it looks like it works at the moment, and allows avoiding the use of redirect what was mentioned earlier .Somewhere int the onConstruct area or initialize someone can set up $this->accessDenied property to true if accesss is denied for a certain user. Oh, one thing yet: it all is in one central class all controllers extend.

public function beforeExecuteRoute($dispatcher)
{
    if ($this->accessDenied===true&&($this->dispatcher->getControllerName()!="auth"||$this->dispatcher->getActionName()!="accessdenied")) {
        $this->dispatcher->forward(array(
                    'controller' => 'authentication',
                    'action' => 'accessdenied'
        ));
        return false;
    }    
}


9.8k

Thank you, dschissler, for your reply. I would like to admit, that in my circumstances my way, i've posted nearly at the same time with your post works for me very well (my application works in a certain way and it allows me using that beforeExecuteRoute example) and i don't have to redirect nothing - i stay on the same URL. Furthermore i see that no other action is invoked. At the moment solved.



9.8k

I'll have to rethink it all. I am sure all the information here is very useful.

I had similar issue as well. I banged my head on this one couple of times.

The solution is pretty simple though.

The best approach is to use dispatcher forwards. If you really need to update URL bar in user's browser, well then you need HTTP header redirect.

Instead of just doing:

                $this->response->redirect(['for' => 'myNamedRoute']);

This works much faster:

                $this->response->redirect(['for' => 'myNamedRoute']);
                //Change HTTP response code as per standards
                $this->response->setStatusCode(303); //This is really optional
                //Make sure that code below does not get executed when we redirect, the other way we get SLOW redirects
                exit($this->response->send());
edited Jan '16

Well, in my case that takes 1000 ms to complete, while forcelly stopping flow with exit(); after output headers are flushed takes only 20 ms. It is clear that returing false; or simple:

return;

will not stop the execution. After you send Location HTTP header field, client is not suppose to do any request to that resource anymore, but it is being sent to another resource. PHP's gabage collector will trash the memory contents anyway...