Universal PHP error and exception handler class for Codeigniter

One of the php disadvantages is that internal PHP functions uses built-in error reporting system, while object oriented extensions use exceptions. In this article I’ve presented custom Codeigniter class that handles all uncaught exceptions thrown during a runtime. That solution works sufficiently with modern code, but standard php errors are not under its control. My aim was to handle all system wide errors and exceptions within just one class and in the same way.

A simple solution to achieve this is to use set_error_handler() function. It’s similar to set_exception_handler(), but expects error details instead of exception object. When handler function is called, it throws new ErrorException with error details passed to the construct. This simple modification translates every ocurred error into uncaught exception, so php errors and exceptions are treated exactly the same way. Functions like printException() and logException() can be reused, so there is no need to write new functions just for regular errors purpose.

Another issue is controlling which errors should be handled. I’ve decided to check the occured error level against current error_reporting value, if bitwise ‘and’ result is 0, then error is just ignored. This allows you to set error_reporting(E_ALL ^ NOTICE) to ignore all notices, just like in default php error handling mechanism.

One signifficant thing to notice while using this solution is that every error handled by provided class will stop the script. So if you have error_reporting(E_ALL) set, every notice/warning will terminate the script. This happens because execution will always stop after the exception_handler is called.

class ErrorHandler extends BaseLibrary {

    protected $oException;

    public function __construct() {
        parent::__construct();
        set_exception_handler(array($this, 'handleException'));
        set_error_handler(array($this, 'handleError'));
    }

    /**
     * Handles errors regarding error_reporting value
     * @param int $errno
     * @param string $errstr
     * @param string $errfile
     * @param string $errline
     * @throws ErrorException
     */
    public function handleError($errno, $errstr, $errfile, $errline) {
        if (error_reporting() & $errno) {
            throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
        }
    }

    /**
     * Handles exception regarding ENVIRONMENT constant
     * Execution will stop after this function is called.
     * @param Exception $oException
     */
    public function handleException(Exception $oException) {
        $this->oException = $oException;

        switch (ENVIRONMENT) {
            case 'development':
            case 'testing':
                $this->printException();
                $this->logException();
                break;
            case 'production':
                $this->logException();
                break;
        }
    }

    /**
     * Prints readable exception content to the client
     */
    private function printException() {
        print("<pre>");
        print("Code: " . $this->oException->getCode() . "<br/>");
        print("Message: " . $this->oException->getMessage() . "<br/>");
        print("File: " . $this->oException->getFile() . "<br/>");
        print("Line: " . $this->oException->getLine() . "<br/>");
        print("Trace: " . $this->oException->getTraceAsString() . "<br/>");
        print("</pre>");
    }

    /**
     * Logs exception in application/logs
     * Requires $config['log_threshold'] to be >= 1 (application/config/config.php)
     */
    private function logException() {
        $this->CI->logger->logException($this->oException);
    }

}

Leave a Reply

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