Recent Posts
- (09/10) Fixing Warning: the ECDSA host key for 'github.com' differs from the key for the IP addressTAGS:Web Server Admin
- (12/26) CakePHP 3 - Getting List of Column Definitions from a Table (like schema())TAGS:CakephpCake3
- (09/14) Change Order of Loaded Behaviors in CakePHP 3TAGS:Cake3CakephpWeb ProgrammingPhp
- (05/29) CakePHP 3 - Accept JSON Header Only Working When Debug FalseTAGS:Web ProgrammingCakephpCake3
- (05/23) Remove All Events from Google Calendar (Reset Calendar)TAGS:Web ProgrammingPhp
- (11/08) Google Tag Manager (GTM) Not Firing Default PageView EventTAGS:Web ProgrammingJavascriptGoogle Tag Manager
- (10/13) In PHP, how do you get __toString() Magic Method Result without calling echo?TAGS:CakephpCake3Cakephp 13PhpWeb Programming
- (11/14) Getting output from shell_exec() at all timesTAGS:Web ProgrammingWeb Server Admin
Subscribe to my feed
MainelyDesign.com Blog
Controlling CakePHP Error Handling When Debug = 0
Posted on 04/19/2010 at 04:27 pm by Kevin Wentworth
Viewed 28,123 times | 1 comment
I finally had a client request a piece of functionality that required me to program CakePHP so I could better control the default error handling when the site is in production mode (i.e. debug is set to 0). By default, CakePHP will throw a 404 page not found header whenever ANY errors occur on a production site with debug equal to zero. This works great, most of the time. But what about when you are having database connectivity issues? Say when there are too many mysql connections to that overloaded shared hosting box? Modifed CakePHP error handling to the rescue.
Override Default AppError Functionality
By default, when your website has a debug level of 0, CakePHP will automatically use AppError::error404() to communicate error messages. This is done to prevent any sensitive data being released through error messages. However, if you want to actually use error methods other than error404() on a production site, you must do a little trick, I picked up:
- function __construct($method, $messages) {
- Configure::write('debug', 1);
- parent::__construct($method, $messages);
- }
This basically makes your site work as if Configure::write('debug', 0); but sets the erorr class to have a debug of 1, so different messages can be used and not just the 404 error message function.
Hijack CakePHP's Default Error Handling
The next step is hijacking all the CakePHP error methods that you need and make them do what you want. For me, this was the missing table and missing database errors. But, I also wanted to check the 404 error and make sure there wasn't database connectivity issues (My 404 page requires a database lookup, so it wouldn't work if there wasn't any DB connection). I decided to make a few functions that would simplify the code:
Checking for DB Connectivity: (Thanks to Miles)
- function _testDBConnectivity() {
- Configure::write('debug', 0); //hide messages in case DB isn't available
- $this->DB = ConnectionManager::getDataSource('db_connection_name');
- if(!$this->DB->isConnected()) {
- return false;
- } else {
- return true;
- }
- }
Hooking into missingTable() and missingDatabase():
Notice the _genericErrorMessage(); calls in the first line of each function.
- function missingTable($params) {
- $this->_genericErrorMessage(); //won't return unless debug is > 0
- 'model' => $className,
- 'table' => $table,
- 'title' => __('Missing Database Table', true)
- ));
- $this->_outputMessage('missingTable');
- }
- $this->_genericErrorMessage(); //won't return unless debug is > 0
- 'title' => __('Scaffold Missing Database Connection', true)
- ));
- $this->_outputMessage('missingScaffolddb');
- }
Hooking into error404() (needed to force the message, b/c I know an error has happened):
If DB fails, show the genericErrorMessage() and force it to show, even if debug isn't 0
- function error404($params) {
- if(!$this->_testDBConnectivity()) {
- $this->_genericErrorMessage(true); //won't return unless debug is > 0
- }
- $url = $this->controller->here;
- }
- $url = Router::normalize($url);
- 'code' => '404',
- 'name' => __('Not Found', true),
- 'message' => h($url),
- 'base' => $this->controller->base
- ));
- $this->__outputMessage('error404');
- }
Function to output customized error message when database connectivity goes down:
- //checks public debug level setting and "hijacks" errors if public debug level is set to 0
- //....and no DB connection, otherwise cakephp's error message show (for development)
- function _genericErrorMessage($override = false) {
- $publicDebugLevel = Configure::read('public.debugLevel');
- if($publicDebugLevel == 0 or $override) {
- Configure::write('debug', 0); //eliminate all future warnings
- $this->controller->layout = Configure::read('siteLayout'); //set layout
- $this->controller->theme = Configure::read('siteTheme'); //set theme
- $this->_outputMessage('genericError'); //output generic error message
- }
- }
Keeping the Search Engines in Mind
I'm sending a 500 error along with the customized error message, because I want search engines to know there was an issue with the site, not a 404 page missing error. Hopefully, this will help eliminate the risk of search engines thinking the page is gone for good.
Wrapping Up CakPHP Error Handling Overrides
What I like most about this approach is the ability to still use the CakePHP error handling when your site isn't in production mode. And, when it's in production mode it will show a 404 error message unless it's a database error. One difference between my setup and the default CakePHP setup, is that I have an additional configuration variable that I use for setting the debug level (it's part of CMS logic). You cannot use just CakePHP's debug setting, because it will be set to 1 by the __constructor() function of the AppError class.
Cheers,
-Kevin
Tags for Controlling CakePHP Error Handling When Debug = 0
Cakephp | Web Programming | Seo | Php | Mysql | Database | Example | Tutorial
Comments for this Posting
Sorry, comments are closed for this posting.
Please Email Kevin if you have any questions. Thanks!
Posted by chad
on 15/9/10
I updated the error404() in my AppError class to start with:
// When CakePHP's 'debug' is set to 0 for production mode the
// Cake library ignores the method name you passed to the
// cakeError() function. Instead it calls this error404()
// function.
//
// To be able to call our own error views in production mode
// we pass the error name in using the $params argument and
// then here we check for that parameter name and call the
// correct method.
//
// Example: to call the soapLookupFailed() method call
// cakeError() via:
//
// $error_params = array('error_method' => 'soapLookupFailed');
// $this->cakeError('soapLookupFailed', $error_params);
if(array_key_exists('error_method', $params)) {
call_user_func(array($this, $params['error_method']), $params);
return;
}