Refinement of the standard error handling mechanism in CodeIgniter

    CodeIgniter provides good error handling capabilities, but they seemed insufficient to me for the following reasons:
    • no exception handling capability
    • there is no way to notify the site administrator of errors through mail
    • rather scanty information about errors that occurred (in the framework with which I worked earlier, the error text is supplemented by a dump of global variables, which greatly facilitates the debugging process, I would like to see a similar scheme in CodeIgniter)

    We will fix it =)

    Exception handling (see option without editing kernel files below)


    We specify an exception handler in the file /system/codeigniter/CodeIgniter.php
    set_exception_handler ('_ exception_handler2');
    

    next to the line
    set_error_handler ('_ exception_handler');
    

    now, when an exception occurs, the _exception_handler2 method from the /system/codeigniter/Common.php file will be called .

    And here is the method itself:
    / **
    * Exception handler
    *
    * /
    function _exception_handler2 ($ errstr)
    {
    	$ error = & load_class ('Exceptions');
    	// Display the text about the exception on the screen
       echo $ error-> show_error ('error', nl2br ($ errstr));
    	// Should we log the error? No? We're done ...
    	$ config = & get_config ();
    	if ($ config ['log_threshold'] == 0)
    	{
    		return
    	}
    	// Write a message to the log
    	$ error-> log_exception ('Exception', $ errstr, '', '');
    	exit
    }
    


    Mail notification and additional error information


    In order for the administrator to receive a notification about errors on the site in the mailbox, you must specify the administrator's email address in the /system/application/config/config.php file :
    / *
    | ------------------------------------------------- -------------------------
    | Admin notification of errors on the site
    | ------------------------------------------------- -------------------------
    |
    | If you want the administrator to receive emails about errors and exceptions
    | Set the next parameter to the address of the administrator's mailbox
    |
    * /
    $ config ['log_to_email'] = 'admin@site.ru';
    

    If you do not want messages to be sent, do not specify this parameter or leave it blank.

    We expand the base class Exceptions - in the directory / system / application / libraries /
    create the file MY_Exceptions.php with the following contents:
    class MY_Exceptions extends CI_Exceptions
    {
    	/ **
    	 * Exception Logger
    	 *
    	 * The method replaces the basic adding features
    	 * send a message to the site administrator about errors
    	 * and output additional information to the log
    	 *
    	 * @access private
    	 * @param string the error severity
    	 * @param string the error string
    	 * @param string the error filepath
    	 * @param string the error line number
    	 * @return string
    	 * /
    	function log_exception ($ severity, $ message, $ filepath, $ line)
    	{
    		// Send a message to the site administrator
    		$ this-> adminmail ($ message);
    		$ severity = (! isset ($ this-> levels [$ severity]))? $ severity: $ this-> levels [$ severity];
    		// Add message text to dumps of environment variables
    		$ message. = "\ n". $ this-> GetGlobalVariables (). $ filepath. ' '. $ line. "\ n \ n";
    		log_message ('error', 'Severity:'. $ severity. '->'. $ message, TRUE);
    	}
    	/ **
    	 * 404 Page Not Found Handler
    	 * 
    	 * The method complements the basic ability to send a message to the administrator
    	 * in case of an error
    	 *
    	 * @access private
    	 * @param string
    	 * @return string
    	 * /
    	function show_404 ($ page = '')
    	{	
    		// Send a message
    		$ message = '404 Page Not Found ->'. $ page;
    		$ this-> adminmail ($ message);
    		parent :: show_404 ($ page);
    	}
    	/ **
        * Returns a dump of environment variables
        *
        * @return string dump environment variables
        * /    
        function GetGlobalVariables ()
        {
    		$ content = 'REMOTE_ADDR ='. $ _ SERVER ["REMOTE_ADDR"]. "\ n";
    		if (isset ($ _ SERVER ["HTTP_REFERER"]))
    		{
    			$ content. = 'HTTP_REFERER ='. $ _ SERVER ["HTTP_REFERER"]. "\ n";
    		}
    		$ content. = 'USER_AGENT ='. $ _ SERVER ["HTTP_USER_AGENT"]. "\ n";		
    		$ content. = '$ _SERVER [\' REQUEST_URI \ '] =';
            $ content. = var_export (@ $ _ SERVER ['REQUEST_URI'], true);
            $ content. = "\ n". '$ _ GET =';
            $ content. = var_export (@ $ _ GET, true);
            $ content. = "\ n". '$ _ POST =';
            $ content. = var_export (@ $ _ POST, true);
            $ content. = "\ n";
            return $ content;
        }
    	/ **
    	 * The method sends an error message to the administrator by mail
    	 * 
    	 * @return 
    	 * @param object $ message
    	 * /
    	function adminmail ($ message)
    	{
    		$ CI = & get_instance ();
    		// If the config is not loaded - load
    		if (! isset ($ CI-> config))
    		{
    			$ CI-> config = & load_class ('Config');
    		}
    		// If the bootloader is not loaded - load
    		if (! isset ($ CI-> load))
    		{
    			$ CI-> load = & load_class ('Loader');
    		}
    		// Download the email class
    		if (! isset ($ CI-> email))
    		{
    			$ CI-> email = & load_class ('Email');
    		}
    		// For the postal class, the Language class is required
    		if (! isset ($ CI-> lang))
    		{
    			$ CI-> lang = & load_class ('Language');
    		}
    		// Administrator mailing address
    		$ email = $ CI-> config-> item ('log_to_email');
    		// If the address is not specified - do nothing
    		if (! strlen ($ email))
    		{
    			return
    		}
    		// Send
    		$ CI-> email-> from ('noreply');
    		$ CI-> email-> to ($ email);
    		$ CI-> email-> subject ('An error occurred on the site');
    		$ CI-> email-> message ($ message);
    		$ CI-> email-> send ();
    	}
    }
    


    Do not forget. that to enable the logging mechanism it is necessary to specify the log_threshold parameter value '1' in the /system/application/config/config.php file .

    You can download the sources ( CodeIgniter.php and Common.php files from CodeIgniter 1.7.2 )

    The code is quite simple - I think that everything is clear from the source.
    If you still have questions, I will be happy to answer in the comments.

    UPDATE: Adding an exception handler using hooks


    In the comments, Mordred advised using hooks instead of editing kernel files to call the installation code of the exception handler and the handler itself - thanks for the advice, I did so.

    First you need to enable the cookie mechanism, for this, in the /system/application/config/config.php file, enable_hooks parameter is set to TRUE :
    $ config ['enable_hooks'] = TRUE;
    


    Then install the hook itself in the file /system/application/config/hooks.php write:
    $ hook ['pre_system'] = array (
                                    'class' => '',
                                    'function' => 'addExceptionHandler',
                                    'filename' => 'exception_hook.php',
                                    'filepath' => 'hooks'
                                    );
    


    This code means that at startup, the addExceptionHandler method will be called from the /system/application/hooks/exception_hook.php file . Here are the contents of this file:
    if (! defined ('BASEPATH')) exit ('No direct script access allowed');
    	/ **
    	* Install exception handler
    	*
    	* /
    	function addExceptionHandler ()
    	{
    		set_exception_handler ('_ exception_handler2');
    	}
    	/ **
    	* Exception handler
    	*
    	* /
    	function _exception_handler2 ($ errstr)
    	{
    		$ error = & load_class ('Exceptions');
    		$ error-> adminmail ('1');
    		// Display the text about the exception on the screen
    	    echo $ error-> show_error ('error', nl2br ($ errstr));
    		// Should we log the error? No? We're done ...
    		$ config = & get_config ();
    		if ($ config ['log_threshold'] == 0)
    		{
    			return
    		}
    		// Write a message to the log
    		$ error-> log_exception ('Exception', $ errstr, '', '');
    		exit
    	}
    


    As a result, the core files of the framework remain intact.
    Download new sources here .

    At the same time, small improvements were made - if the error occurred before the controller was loaded, sending notifications to the administrator did not work, since the necessary classes were not loaded for this, now there is a check and if the desired class is not loaded, then load it, plus minor changes.

    Original article

    Also popular now: