I developed a solution similar to this because I encountered a completely blank / white screen in Yii. Research online kept giving the answer as being to set php.ini’s DISPLAY_ERRORS - that was wrong because the reason for the blank screen is YiiBase is suppressing the errors using the ‘@’ symbol.
It was painful enough to diagnose, even though the cause was a simple syntax error, that I decided I didn’t want to deal with it again. Now on deciding to document my approach I came across this thread.
My approach has a little more finesses I think, because it only checks for errors that the PHP docs say cannot be caught by custom error handlers. Any other error codes we assume have been caught (or could be caught) by other mechanisms so we can ignore them.
Same as the last post, I call this from the WebApplication’s init method. I avoid the whole issue about how to terminate the program with the correct logging still occurring, by leaving it to the other shutdown handlers. This will work fine if the error occurs during normal ‘run’ processing, but not otherwise - in which case turning YII_DEBUG to true will always reveal the problem.
public function onShutdown()
{
/*
According to PHP description of set_error_handler:
The following error types cannot be handled with a user defined
function:
E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING,
E_COMPILE_ERROR, E_COMPILE_WARNING
(http://www.php.net/manual/en/function.set-error-handler.php)
So the following checks to see if one of the above errors has
occurred, since they can't have been caught by the Yii error handler
*/
if (($error = error_get_last()) !== null
&&
in_array($error['type'], array (E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING))
) {
$log="Unhandled PHP error code {$error['type']} at shutdown: {$error['message']} ({$error['file']}:{$error['line']})\n";
if(isset($_SERVER['REQUEST_URI'])) {
$log.='REQUEST_URI='.$_SERVER['REQUEST_URI'];
}
Yii::log($log,CLogger::LEVEL_ERROR,'php');
if (YII_DEBUG) {
Yii::app()->displayError($error['type'], $error['message'], $error['file'], $error['line']);
}
/*
Note we don't want to die here - we want to allow shutdown to continue, otherwise
(for example) messages won't get logged / distributed. However if the error gets detected
before other shutdown handlers have been registsred, or after they've run, then all bets are
off - in which case YII_DEBUG being set to true will catch it.
*/
}
}