⬆️ ⬇️

Refinement of the standard error handling mechanism in CodeIgniter

CodeIgniter provides quite good error handling capabilities, but they seemed to me insufficient for the following reasons:



We will fix it =)



Exception handling (see below option without editing kernel files)



Specify the 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.



But the actual method itself:

 / **
 * Exception handler
 *
 * /
 function _exception_handler2 ($ errstr)
 {
	 $ error = & load_class ('Exceptions');
	
	 // Display the exception text 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;
 }




Notification by mail and additional information on errors



In order for the adminstrator to receive notification of errors on the website to the mailbox, it is necessary in the file /system/application/config/config.php to specify the email address of the administrator:

 / *
 | ------------------------------------------------- -------------------------
 |  Notification administrator about errors on the site
 | ------------------------------------------------- -------------------------
 |
 |  If you want the administrator to receive letters about errors and exceptions
 |  Specify the following address with the address of the mailbox administrator
 |
 * /
 $ 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.

')

Extend 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
	  *
	  * Method replaces basic adding features
	  * send error message to site administrator
	  * and display additional information in 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];
		
		 // Supplement the message text with 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 the 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 mail administrator
	  * 
	  * @return 
	  * @param object $ message
	  * /
	 function adminmail ($ message)
	 {
		 $ CI = & get_instance ();
		
		 // If the config is not loaded - we 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');
		 }
		
		 // Load the class email
		 if (! isset ($ CI-> email))
		 {
			 $ CI-> email = & load_class ('Email');
		 }
		
		 // For the mail class, the Language class is required.
		 if (! isset ($ CI-> lang))
		 {
			 $ CI-> lang = & load_class ('Language');
		 }
		
		 // Email address of the administrator
		 $ email = $ CI-> config-> item ('log_to_email');
		
		 // If the address is not specified - do nothing
		 if (! strlen ($ email))
		 {
			 return;
		 }
		
		
		
		 // Sending
		 $ CI-> email-> from ('noreply');
		 $ CI-> email-> to ($ email);
		 $ CI-> email-> subject ('There was an error on the site');
		 $ CI-> email-> message ($ message);

		 $ CI-> email-> send ();
	 }
 }




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



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



The code is pretty simple - I think everything is clear by source.

If all the same questions arise - I will be happy to answer in the comments.



UPDATE: Adding an exception handler using hooks



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



First you need to turn on the cookie mechanism. To do this, in the /system/application/config/config.php file, enable_hooks parameter is set to TRUE :

 $ config ['enable_hooks'] = TRUE;




Then we install the hook itself in the /system/application/config/hooks.php file, we write:

 $ hook ['pre_system'] = array (
                                 'class' => '',
                                 'function' => 'addExceptionHandler',
                                 'filename' => 'exception_hook.php',
                                 'filepath' => 'hooks'
                                 );




This code means that when the system starts, the addExceptionHandler method will be called from the file /system/application/hooks/exception_hook.php . Here is the contents of this file:

 if (! defined ('BASEPATH')) exit ('No direct script access allowed');

	 / **
	 * Install an exception handler
	 *
	 * /
	 function addExceptionHandler ()
	 {
		 set_exception_handler ('_ exception_handler2');
	 }
	
	
	 / **
	 * Exception handler
	 *
	 * /
	 function _exception_handler2 ($ errstr)
	 {
		 $ error = & load_class ('Exceptions');
		
		 $ error-> adminmail ('1');
		
		 // Display the exception text 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 framework core files remain intact.

Download the new sources here .



Minor improvements were made at the same time - if an error occurred before loading the controller - sending notifications to the admin did not work, since the necessary classes were not loaded for this, now there is a check and if the required class is not loaded, then we load it, plus minor changes.



Original article

Source: https://habr.com/ru/post/74381/



All Articles