make way for ducklings

Creative Commons License photo credit: shoothead

This teknoid blog post describes an excellent method of refining Cake’s default error handling.
Quick reminder: by default, if your debug level is set to 0, cake will always redirect your user to the error404.ctp under app/views/errors).

Edit Jan 5, 2011: The information in this post is for Cake 1.2/1.3. See COTP’s comment below if you’re using Cake 2.0 or newer.

I recently had an issue with the 404 error page in an application I’m coding.
The application let’s a user log in to the system, and after a user logs in, there’s a box at the top right of the screen that displays the user’s name like this:

My application's login information box

My application's login information box

When I go to a non-existing URL, CakePHP redirects me to the error404.ctp page, as expected. However, as none of my controllers is involved (and especially not my app_controller which sets the logged in user name for default.ctp) – the login information does not exist, and my 404 page looks like this:

My application with no login information

My application with no login information

This saddened me to no end. Actually, it saddened my Business Analyst, and I do not like it when he’s unhappy. I therefore read and re-read the aforementioned teknoid’s post, until I found a silly hack that does the trick:

//File: app/app_error.php
<?php
class AppError extends ErrorHandler {

    function __construct($method, $messages) {
        parent::__construct($method, $messages);
    }

    function _outputMessage($template) {
        $this->controller->redirect('/error404');
        $this->controller->afterFilter();
    }

    ...
}
?>

All app_error.php does is take control of error handling from Cake’s default. All I do in it is redirect the incoming request to the /error404 path.
In routes.php, I connect /error404 to a specific controller/action pair:

//file: app/config/routes.php
Router::connect('/error404', array('controller' => 'bulls', 'action' => 'error'));

And in bulls_controller.php – just add an empty error function:

//file: app/controllers/bulls_controller.php
function error() {}

Last – add the error.ctp view:

//file: app/views/bulls/error.ctp
<h1>404. Oops. Dais.</h1>

And that’s it! Now, when the user enters a non-existing URL, Cake is going to redirect it to the bulls controller. Because of this, I regain the user’s context in my error page!

(Note, there’s probably an easier way to do it, but the point is, you can use this technique whenever you set up some data for your default template that you wish was available for your error page as well).

Popularity: 5% [?]

 

3 Responses to CakePHP: Keeping login information on error pages

  1. COTP says:

    For CakePHP 2.0+, you can copy lib/Cake/Controller/CakeErrorController.php to app/Controller/CakeErrorController.php and use the usual $this->set() function.

    Great post! Very informative :-)

  2. COTP says:

    ** Just to clarify, in CakeErrorController.php (the copy in app/Controller/)

    public function beforeRender() {
        parent::beforeRender();
        $this->set('user_id', $this->Auth->user('id'));
        foreach ($this->viewVars as $key => $value) {
            if (!is_object($value)){
                $this->viewVars[$key] = h($value);
            }
        }
    }
  3. Duck Ranger says:

    @COTP – great, thanks! I edited to mention this is old Cake :)

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>