Redirects with Ajax

By sunertl (sunertl)
Redirects with Ajax are not really simple to do. When you redirect within the same controller, you can use setAction() instead but what if you want to redirect to another controller? I figured out a quite simple way using sessions, postet it - and got back the IMHO perfect solution by gwoo.
Cakebaker already wrote two times about redirecting with Ajax:
http://cakebaker.42dh.com/2006/03/15/redirect-with-ajax/
http://cakebaker.42dh.com/2006/03/28/a-simple-redirect-component/
He does it using a client-side redirect with javascript. I don't like client-side solutions as it is something I cannot controll. I figured out a way using session (storing the desired layout in a session, then redirect and load the layout according to the stored layout) but gwoo showed me a much more efficient way:

Simply override the default redirect-method in the appcontroller by using:

Controller Class:

Download code <?php 
function redirect($url$status null){
    
$ajax = ($this->RequestHandler->isAjax())
    ? (
$url{0} != '/') ? '/ajax/' '/ajax' null;
    
parent::redirect($ajax.$url$status);
}
?>


you are done!

Be careful if this solution conflicts in any way with your custom routings. But in most cases it will work perfektly.

using this way does not even require you to change any code written already :-).

 

Comments 92

CakePHP Team Comments Author Comments
 

Comment

1 In plain English

I'm easily confused by the terse language constructs when it's singular. Nest it like that and I'm really lost! :)

So for those like me, I believe it can be rewritten but still be 'terse' like:

Controller Class:

<?php 
function redirect($url$status null) {
    if (
$this->RequestHandler->isAjax()) {
        
$url '/ajax/'.ltrim($url'/');
    }
    
parent::redirect($url$status);

?>


And thanks for this! It's exactly what I'm looking for. Now redirect fixes happen without any change to the code.
Posted Dec 31, 1969 by Tom OReilly
 

Comment

2 Making it 1.2 ready

Also, the api is a bit different for 1.2. It now takes a third parameter, so be sure to pass that through:

Controller Class:

<?php 
function redirect($url$status null$exit false) {
...
    
parent::redirect($url$status$exit);
}
?>


Since it's adding a param with a set default, it should work just fine in 1.1.x as well, but the third param will just be ignored.
Posted Dec 31, 1969 by Tom OReilly
 

Comment

3 Alternative

Hi,

I would suggest the following:

function redirect($url, $status = null, $die = true) {
    if ($this->RequestHandler->isAjax() || isset ($this->params['requested'])) {
        echo $this->requestAction($url, array (
                'return'
            ));
    } else {
        parent :: redirect($url, $status);
    }
    if ($die) {
        die;
    } else {
        return false;
    }
}

Or a permutation thereof.
Posted Dec 31, 1969 by Andy Dawson
 

Comment

4 Error

I got this error...

Notice: Undefined property: MyController::$RequestHandler in /home/......
Posted Apr 25, 2007 by Roy Evangelista
 

Comment

5 Error Solved

Sorry, i forgot to include the RequestHandler component......
Now it's working fine.....
Posted Apr 25, 2007 by Roy Evangelista
 

Comment

6 update for 1.2

i found out, that in 1.2 there are arrays use in the redirects. so i updated the function a little bit:


function redirect($url, $status = null, $exit = false) {
    $temp = $url;
    if(is_array($url)) {
        $temp = '/';
        $temp .= isset($url['controller']) ? $url['controller'] : $this->params['controller'];
        $temp .= '/';
        $temp .= isset($url['action']) ? $url['action'] : $this->params['action'];
        $url = '';
    }
    $ajax = ($this->RequestHandler->isAjax()) ? ($temp{0} != '/') ? '/ajax/' : '/ajax' : null;
    parent::redirect($ajax.$temp, $status, $exit);
}


i do not know if it is a really nice solution but it works quite good for me. further improvements are welcome!
Posted Aug 7, 2007 by sunertl