Dealing with errors in CakePHP

Chances are if your app is already out in production, you have your debug level set to ‘0’. This is probably good news, since the users will not be seeing any nasty errors and in the worst case, they’ll see a blank page or a ‘not found’ page in case of an application error. (You might have noticed that when running with debug = 0, PHP errors are disabled and all application errors will point the user to a standard 404 page).

However, this may not be good enough for you and you’d like to extend the error handling capabilities of your app…

First, let’s take a look at what types of errors we should handle, and how to deal with them properly.

Technically we have two types of errors: PHP errors and CakePHP errors. CakePHP errors (application errors) would be something that is triggered by your application, for example a missing view file or a missing database table, PHP errors would be something like a fatal error that’s caused by a missing bracket or a notice of an undefined variable.
It goes without saying that in production your code should not have any missing brackets or missing views, but there are cases (i.e. division by zero) where a problem can slip by even with rigorous testing. Surely, you don’t want your users to see it, but it would be good for the developer/manager to know if that happens.

Let’s take a look at what to do with our PHP errors… It is important to realize that PHP errors should be dealt with completely separately from the CakePHP errors. Thankfully you can pretty easily control what happens when a PHP error arises by using our good ol’ .htaccess or php.ini. A simple google search will teach you all you need to know about how to ensure that PHP errors are logged, but not displayed to the user.

So what about CakePHP errors?
To extend CakePHP’s error handling you should create a file called app_error.php in your /app/ directory.

You then neeed to create a class there: class AppError extends ErrorHandler…

Now, you can override any default CakePHP error handling methods, to suit your own needs.

Here’s a trick to allow CakePHP errors to be emailed to the developer, while running with debug = 0, set in core.php:

class AppError extends ErrorHandler {

function __construct($method, $messages) {
   Configure::write('debug', 1);
   parent::__construct($method, $messages);
}

function _outputMessage($template) {
   $this->controller->render($template);
   $this->controller->afterFilter();

   App::import('Core', 'Email');

   $email = new EmailComponent;

   $email->from = 'CakePHP <cakephpapp@yourdomain.com>';
   $email->to = 'Developer <somedeveloper@yourdomain.com>';
   $email->sendAs = 'html';
   $email->subject = 'Error in my CakePHP app';

   $email->send($this->controller->output);
}

}

So now, the end-user will not see any errors (PHP or CakePHP), but the developer should have PHP errors logged on the server and CakePHP errors sent to him in an email.

It is also a good idea to add some output so that the user is not stuck looking at a blank page. You can easily extend above method to have:

$this->controller->output = null;
$this->controller->render('someGenericErrorTemplate');
echo $this->controller->output;

You could just as easily log the errors to a file or define your own error methods (see cake’s default error.php) to add improved error logging and handling.

I’m sure this approach goes against some rules, but I have not seen a different way to handle this situation… so any suggestions/improvements are certainly welcomed.

P.S.
primeminister pointed out that by using Object::cakeError() (see API) as well as defining some methods in App Error, one can easily add a more robust error handling to deal with various situations that can arise in your application. In a way you can think of using cakeError() within your app similarly to how you’d use trigger_error() in good ol’ PHP.

%d bloggers like this: