10 Steps to properly do PHP Bug Tracking and Fixing as Fast as possible – Part 3

Sharing is caring!

7. Send PHP Errors to an Error Log File

8. Add more Error Context Information to PHP Errors Logs

7. Send PHP Errors to an Error Log File

If you should not display PHP errors on the Web pages, you should be able to see them somehow. A better alternative is to send the errors to a error log file. This way you can watch what is going on without disclosing sensitive information to your site users.

You can enable PHP error logs adding a few configuration lines to your php.ini file. Additionally you also set other useful PHP options.
error_reporting = E_ALL
log_errors = On
error_log = /path/to/php_error_log
log_errors_max_len = 0
ignore_repeated_errors = On
ignore_repeated_source = Off
report_memleaks = On
track_errors = On
html_errors = Off

8. Add more Error Context Information to PHP Errors Logs

PHP error warnings may be useful to debug your code but sometimes they lack of context that could help understanding the problem faster.

For instance the error may have happened in a certain line of a function but if you do not know exactly what are the parameters passed to that function, nor the location of the code that called that function, you may have a hard time figuring why the error occurred.

You can enhance your PHP error logs with more error context information if you override the PHP default error log handler. You can do that using the PHP function set_error_handler. You can define a new function that will inspect the current PHP execution context and add more details to the PHP error log.

PHP error handlers are fine but they are not able to intercept fatal PHP errors, like for instance including a PHP file with an incorrect path, or creating an object of class with an incorrect name, etc..

A workaround for that limitation of PHP error handlers is to register PHP shutdown function to check if PHP ended the execution with a fatal error. That can be done with the PHP function register_shutdown_function.

You can do all this from your configuration class. Here is a more complete version of the class.
class configuration
{
/*
* store error messages in case an error happens
*/
public $error = ”;

/*
* Path of the main application relative to the current directory
*/
public $application_path = ‘.’;

/*
* Host name of the site to compose absolute URLs
*/
public $host = ‘www.mysite.com’;

/*
* name of the site database
*/
public $database_name = ‘production-database’;

/*
* name of the account to access the database
*/
public $database_user = ”;

/*
* password of the account to access the database
*/
public $database_password = ”;

/*
* A common error handler code for fatal and non-fatal errors
*/
Function BaseErrorHandler($error, $message, $file, $line, $backtrace)
{
if($error & error_reporting())
{
$log=array();
switch($error)
{
case E_ERROR:
case E_USER_ERROR:
$type=’FATAL’;
break;
case E_WARNING:
case E_USER_WARNING:
$type=’WARNING’;
break;
case E_NOTICE:
case E_USER_NOTICE:
$type=’NOTICE’;
break;
default:
$type=’Unknown error type [‘.$error.’]’;
break;
}
$log[]=str_repeat(‘_’,75);
$request_uri = GetEnv(‘REQUEST_URI’);
$agent = GetEnv(‘HTTP_USER_AGENT’);
$log[]=$type.’: ‘.$message.’ in line ‘.$line.’ of file ‘.$file.
‘, PHP ‘.PHP_VERSION.’ (‘.PHP_OS.’)’.
(strlen($request_uri) ? ‘ ‘.$request_uri : ”).
((IsSet($_POST) && count($_POST)) ?
‘ POST=’.serialize($_POST) : ”).
((IsSet($_GET) && count($_GET)) ?
‘ GET=’.serialize($_GET) : ”).
((IsSet($_FILES) && count($_FILES)) ?
‘ FILES=’.serialize($_FILES) : ”).
(strlen($agent) ? ‘ AGENT=”‘.$agent.'”‘ : ”).
(IsSet($_SERVER[‘REQUEST_METHOD’]) ?
‘ METHOD=”‘.$_SERVER[‘REQUEST_METHOD’].'”‘.
($_SERVER[‘REQUEST_METHOD’] === ‘POST’ ?
‘ POST=”‘.serialize($_POST).'”‘ : ”) : ”);
for($level=1;$level < count($backtrace);$level++)
{
$message=’File: ‘.$backtrace[$level][‘file’].
‘ Line: ‘.$backtrace[$level][‘line’].’ Function: ‘;
if(IsSet($backtrace[$level][‘class’]))
$message.='(class ‘.$backtrace[$level][‘class’].’) ‘;
if(IsSet($backtrace[$level][‘type’]))
$message.=$backtrace[$level][‘type’].’ ‘;
$message.=$backtrace[$level][‘function’].'(‘;
if(IsSet($backtrace[$level][‘args’]))
{
for($argument=0;$argument<count($backtrace[$level][‘args’]);
$argument++)
{
if($argument>0)
$message.=’, ‘;
if(GetType($backtrace[$level][‘args’][$argument])==’object’)
$message.=’class ‘.
get_class($backtrace[$level][‘args’][$argument]);
else
$message.=serialize($backtrace[$level][‘args’][$argument]);
}
}
$message.=’)’;
$log[]=$message;
}
error_log(implode(“nt”,$log));
}
if($error==E_ERROR)
exit(1);
}

/*
* Error handler for non-fatal PHP errors
*/
Function CommonErrorHandler($error,$message,$file,$line)
{
$backtrace=(function_exists(‘debug_backtrace’) ?
debug_backtrace() : array());
BaseErrorHandler($error, $message, $file, $line, $backtrace);
}

/*
* Error handler for fatal PHP errors
*/
Function FatalErrorHandler()
{
$error = error_get_last();
if(IsSet($error))
BaseErrorHandler($error[‘type’], $error[‘message’], $error[‘file’],
$error[‘line’], array());
}

/*
* Initialize the configuration loading options from a local script
*/
function Initialize()
{
set_error_handler(array($this, ‘CommonErrorHandler’));
register_shutdown_function(array($this, ‘FatalErrorHandler’));
$local_options = $this >application_path .
‘/configuration/local_options.php’;
if(!file_exists($local_options))
{
$this->error = ‘the application configuration file ‘.
$local_options.’does not exist’;
return false;
}
require($local_options);
return true
}

function Fail()
{
error_log(‘Error: ‘.$this->error);
exit;
}
};

Source From: http://www.phpclasses.org

3 thoughts on “10 Steps to properly do PHP Bug Tracking and Fixing as Fast as possible – Part 3

Leave a Reply

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

Got Project on mind? Let's ConnectContact Us

Secured By miniOrange