CakePHP, beforeFilter, and the Error Error
We all know CakePHP is the bee’s knees for developing web applications, but what’s not so hot is Cake’s handling of error pages. Most developers discover soon enough that they can customize their error pages, most commonly the 404 “not found” page, by creating an appropriately named file, e.g. error404.ctp, within the views/errors folder. Easy peasy, right? Sure, but lurking in the bowels of Cake’s code is a significantly more obscure problem that manifests itself in various ways. Simply put, CakePHP fails to load components and does not run the beforeFilter() function of the AppController, deviating from its normal page-loading process. This can lead to utterly maddening behavior if you do anything important in beforeFilter(), which would be almost always.
An application I’m developing at work runs critical code in beforeFilter() that checks if a user is logged in and uses the results to set the website title and which links appear in the main menu. So you could say that’s fairly important. But on my error pages, Cake would conveniently display no title or main menu whatsoever. Because no debugging messages were displayed, I thought the issue might have been a minor case of a different layout file being used for error pages. But after a thorough combing of Cake’s library code, I discovered the ugly truth within the cake/libs/error.php file: the CakeErrorController class, which is used by the accompanying ErrorHandler class, never calls the beforeFilter() function. This contrasts with the Dispatcher class in cake/dispatcher.php that is responsible for most normal pages—this code eventually runs beforeFilter() within the controller’s _invoke() function, but before that it also calls the controller’s constructClasses() function, which turned out to be a critical part of my solution to this now unwieldy problem.
After attempting several ways of making the error pages run my beforeFilter() code, I found that simply adding $this->beforeFilter(); as the last line of the CakeErrorController constructor seemed to work. The problem with doing this, however, is that I had to change a core file within Cake. As my fellow developers know, this is not an option, so I had to make it work from within my own code. But luckily I was on the right track: the constructor inherits from the AppController constructor, which I was free to modify. So within my application’s app_controller.php file, I added a constructor and copied the code from CakeErrorController, making sure to add my call to beforeFilter() at the end. Amazingly it seemed to work, so I then proceeded to see which lines I could safely comment out, until I was left with just a few lines of code. The constructClasses() function in particular seems to be Cake’s succinct way of loading the components used by the application. After testing several normal pages and error pages alike, I feel fairly confident that I have solved my initial problem. Here’s the code I added to app_controller.php:
function __construct() {
parent::__construct();
if ($this->name == 'CakeError') {
$this->constructClasses();
$this->beforeFilter();
}
}
Since I was forced to put the code in the main AppController class, some side effects may exist: beforeFilter() is potentially called twice on standard pages and perhaps earlier than normal. From what I can tell, this doesn’t affect the application’s performance or behavior. So hopefully this solution will help other CakePHP developers who want their error pages to behave as expected. But surely I am not alone in hoping that future versions of CakePHP will make this workaround unnecessary.
UPDATE: I tweaked the code to include an explicit check for CakeErrorController before running the extra lines of code in the constructor. I found a fail case that had to do with adding new users via the Auth component—new passwords were being hashed twice. So this new snippet should successfully eliminate the possibility of code running twice needlessly.

What about creating an app_error.ctp in /app with:
controller->beforeFilter();
parent::error404();
}
}
?>
That didn’t come out well…one more try:
<?php
class AppError extends ErrorHandler {
function error404() {
$this->controller->beforeFilter();
parent::error404();
}
}
?>
Matt, thanks for the info. Your solution works fine in production mode for the 404 page specifically. I guess I wanted my solution to cover all the other error pages, including ones that are used in development mode, like “missing controller” and “missing action,” etc.
Cheers for this! I was having this problem myself and your solution was heaps better than my own hack. :)
very informative post for beforeFilter of cakphp..helped me lot..thanks..:)
I was having the same problems, and couldn’t overcome the problems until I read your article. Helped a lot, thanks.
I did have a small problem with it though. the code above loaded up the beforeFilter() fine, and I added a beforeRender() aswell, just because my layout needs it. The problem was that even though my components were loaded, they didn’t do anything. I added:
$this->MyNiceComponent->startup($this);
to the bottom of the _construct() and all was fine.
Just thought I’d post it, incase others get a bit stuck.
Hi, nice site, thanks for the infos.
I have a query – I have an app with 20+ classes using AMFPHP. I am using the beforeFilter() to validate requests and it works fine, however I want to store the beforeFilter function centrally. It’s a pain to have it sitting at the top of EVERY class file. I tried having it in a PHP include to no avail. It doesn’t recognize it. Any tips? I’m a bit new to AMF…
Thanks,
S
I haven’t worked with AMF, but if it’s anything like Cake, there should be a file like “app_controller.php” that runs before any individual class file. But for all I know, it might be totally different.
wow… saves me a lot of time… I was working with language links
ex.:
example.com/eng/controllers/action
example.com/fre/controllers/action
and it solve my problem cause each time there was an error my language params was gone… THKS a lot
Hah, it seems not only me got this problem, luckily you Brade solved it already and was kind enough to share the solution, thank you ;)
Great article. I’ve been working on unearthing the same issue on my production API for a couple of hours now. Google has loads of links that describe how to create custom error handling within CakePHP. The issue of calling beforeFilter is critcal to my app and you have saved my sanity. Thanks :-)
Your suggestion has solved my problem with (dynamically set) themes not being detected by CakeError as well. Great tip, thanks man!
This was a great resource. Just wish I would have done this way before I started to parse through the entire Core directory looking for the correct function to import to app_controller.
Awesome, thanks a ton for this! Worked like a charm. :)
Hey there, thanks a lot. That was a great tip!