I think I said a few days ago that I would offer up some ideas for creating your very own custom error handler in PHP. I have barely tested it, but it seems to work okay.
To use the error handler, firstly make sure you have included the class, then add
or for debugging purposes you could usePHP Code:set_error_handler( array('errorHandler','live') );
ps. the directory the specified log file is in must be writable. On RF, if it is outside the web root, you still need to make the directory writable - just send the standard chmod requests, and although they don't strictly speaking chmod, they do enough of something!PHP Code:set_error_handler( array('errorHandler','debug') );
Right, I've added some commenting, but just ask if you want a better explaination.
pps. Warren, it's damn annoying that these code boxes wrap at less than 80 characters width!PHP Code:<?php
/**
* This script may be used and modified by anyone, though I take no
* liabilities resulting from its usage. The script has not been rigorously
* tested.
*
* @author Nick Thornley Feb 2006 <nick@quesmedia.com>
*/
/**
* errorHandler class, to be used in replace of PHP's default error handler
*
* Live mode implementation:
* set_error_handler( array('errorHandler','live') );
*
* Debug Mode implementation:
* set_error_handler( array('errorHandler','debug') );
*
*/
class errorHandler
{
/**
* @var string absolute path to the log file
*/
private static $log_file = 'D:\yoursite.com\phplogs\current.log';
/**
* @var int size at which to start new log file and archive the old (bytes)
*/
private static $max_filesize = 10000;
/**
* @var string used to store any handler error messages
*/
private static $handler_error;
/**
* @var string date format string - follows standard date formatting rules
*/
private static $dateformat = 'r';
/**
* @var string seperator between error information in the log
*/
private static $seperator = ' ';
/**
* @var string An nice (un)informative error message to display the public
*/
private static $fatal_mssg = 'Our site is experiencing temporary problems.';
/**
* Callback function to be used to log errors a live site
*
* @return bool
*/
public static function live()
{
//grab the error array from the function arguments
$e = func_get_args();
//create an array of information we would like to log
$output[] = "[".date(self::$dateformat)."]";
$output[] = $e[0]; //error number
$output[] = $e[2]; //file
$output[] = $e[3]; //line
$output[] = $e[1]; //error message
//create a string out of the output array
$output = implode(self::$seperator,$output);
$output .= "\n";
//Call the function to write to the log file
if(self::_writeLogFile($output) === false){
//help, the error logging function has a problem
//the error has not been logged.
//an error message is held in the var self::$handler_error
return false;
}
//The following switch statement can be used to provide feedback to the
//user browsing the site, dependent on the type of error
switch( $e[0] )
{
case E_NOTICE:
case E_WARNING:
case E_STRICT:
case E_USER_NOTICE:
case E_USER_WARNING:
//do nothing, as the error is not fatal
break;
default:
//fatal error, so clear any output buffers, display the error
//message and exit the script.
if(ob_get_level()){
while (@ob_end_clean());
}
echo self::$fatal_mssg;
die();
}
return true;
}
/**/
/**
* Callback function to be used to display errors to screen for debugging
*
* @return bool
*/
public static function debug()
{
//grab the error array from the function arguments
$e = func_get_args();
//The following switch statement can be used to provide feedback to the
//user browsing the site, dependent on the type of error
switch( $e[0] )
{
case E_NOTICE:
case E_WARNING:
case E_STRICT:
case E_USER_NOTICE:
case E_USER_WARNING:
//non-fatal error, just output a simple inline message
echo '<span class="error">';
echo 'Error ('.$e[0].') on line '.$e[3].' - '.$e[2].' - ';
echo htmlspecialchars($e[1]);
echo '</span> ';
break;
default:
//fatal error, so print out the full error array and exit.
//the output buffer has not been cleared, so any content already
//output will be displayed prior to the error message
echo "<pre>error:";
print_r($e);
echo "</pre>";
die();
}
return true;
}
/**/
//============ PRIVATE CLASS FUNCTIONS FOR FILE MANIPULATION =============//
/**
* Writes data to a file, by default the it overwrites the previous file
*
* @param string absolute file path
* @param string data to write to file
* @param string file open more - default 'wb'
*
* @return bool
*/
private static function _writeFile($file, $data, $mode='wb')
{
if (!$handle = fopen($file, $mode)) {
self::$handler_error = "Cannot open file ($filename)";
return false;
}
if (fwrite($handle, $data) === FALSE) {
self::$handler_error = "Cannot write file ($filename)";
return false;
}
fclose($handle);
return true;
}
/**
* creates and subsequently appends data to the log file.
*
* If the log file exceeds the maximum allowed size, the archiveLogFile
* function will be called to archive the log and start a fresh file.
*
* @param string data to write to file
*
* @return bool
*/
private static function _writeLogFile( $data )
{
//if the log file exists but exceeds the maximum size,
if( is_file(self::$log_file)
&&
filesize(self::$log_file) > self::$max_filesize ){
//attempt to create an archive copy of the log file
if(!self::_archiveLogFile(self::$log_file)) {
return false;
}
}
//append/create file with data
return self::_writeFile(self::$log_file, $data, 'ab');
}
/**
* Simply returns the contents of a file as a string
*
* @param string absolute file path
*
* @return string file contents, or false if an error was encountered
*/
private static function _readFileContents($file)
{
if (!$handle = fopen($file, 'rb')) {
self::$handler_error = "Cannot open file ($filename)";
return false;
}
if (!$contents = fread($handle, filesize($file))) {
self::$handler_error = "Cannot read file ($filename)";
return false;
}
fclose($handle);
return $contents;
}
/**
* Creates a compressed copy of a file + deletes the original (if sucessful)
*
* @param string absolute file path
*
* @return bool
*/
private static function _archiveLogFile($file)
{
//regexp pattern to strip of filename from file path
$pattern = '/([^\/\]*.$)/';
//replacement file name
$replacment = time().'.gz';
$archivefile = preg_replace($pattern, $replacment,$file);
//read current log file into $contents
$contents = self::_readFileContents($file);
if($contents === false){
return false;
}
//write new compressed archived file with content
self::_writeFile($archivefile, gzencode($contents,9), 'wb');
if(!is_file($file)){
return false;
}
//delete the original file
unlink($file);
return true;
}
}//end errorHandler class definition
?>



Reply With Quote

Bookmarks