Do you know how crash-prone your PHP script is?






It’s easy to spot errors when they happen on your developer machine. But how do you deal with error happening on the live server? Or even more important – how do you discover errors happening to your customers?

In PHP you have to possibility to register a function that will be called every time your script terminates. By writing just a few lines of code you can be notified by email when an error occurs and you can more easily debug the errors on the live server.

The following code example tries to get the latest error values as an array and, if errors are found, summarizes an email with error and request data. If no error is found the script has terminated in a normal way without any errors so there is no need to send an error email.

The error information is then sent off to a given email address.

function HandleShutdown() {
  try {
    $errorArray = error_get_last();
    if($errorArray !== NULL){
      // Get error data
      $info = "### ERROR DATA ###".PHP_EOL;
      $info .= print_r($errorArray,true).PHP_EOL.PHP_EOL;
	
      // Get request data (GET, POST and SESSION)
      $info .= "### REQUEST DATA ###".PHP_EOL;
      $info .= print_r($_REQUEST,true).PHP_EOL.PHP_EOL;
		
      $title = "SCRIPT ERROR :: ".ReadableErrorType($errorArray['type']);
      mail("admin@mycompany.com",$title,$info);

      // Check if error is severe enough to notify the user/customer about it
      $type = $errorArray['type'];
      if (($type & E_ERROR) || ($type & E_CORE_ERROR) || ($type & E_COMPILE_ERROR) || ($type & E_USER_ERROR))
      {
        // Display error message on screen...
      }
      ob_flush();
    }
  } catch (Exception $e) {
    // Handle the error?
  }
}

The error type available as $errorArray[‘type’] in the code above is given as a bitmasked value and needs to be translated to make sense. A complete list with description of all error codes can be found on the PHP website.

To translate the errors you can simply write a function like the following one.

function ReadableErrorType($type)
{
  $return ="";
  if($type & E_ERROR) 
    $return.='& E_ERROR ';
  if($type & E_WARNING) 
    $return.='& E_WARNING';
  if($type & E_PARSE)
    $return.='& E_PARSE ';
  if($type & E_NOTICE) 
    $return.='& E_NOTICE ';
  if($type & E_CORE_ERROR) 
    $return.='& E_CORE_ERROR ';
  if($type & E_CORE_WARNING) 
    $return.='& E_CORE_WARNING ';
  if($type & E_COMPILE_ERROR) 
    $return.='& E_COMPILE_ERROR ';
  if($type & E_COMPILE_WARNING) 
    $return.='& E_COMPILE_WARNING ';
  if($type & E_USER_ERROR) 
    $return.='& E_USER_ERROR ';
  if($type & E_USER_WARNING) 
    $return.='& E_USER_WARNING ';
  if($type & E_USER_NOTICE)
    $return.='& E_USER_NOTICE ';
  if($type & E_STRICT) 
    $return.='& E_STRICT ';
  if($type & E_RECOVERABLE_ERROR) 
    $return.='& E_RECOVERABLE_ERROR ';
  if($type & E_DEPRECATED) 
    $return.='& E_DEPRECATED ';
  if($type & E_USER_DEPRECATED) 
    $return.='& E_USER_DEPRECATED ';
  return substr($return,2);
}






Finally we also need to register the shut-down function so it’ll be called when a shut-down occurs. This method call needs to be made early in the script.

register_shutdown_function('HandleShutdown');

The following text is an example of what your error emails might look like, depending on what error and request data that is available when the error occurred.

### ERROR DATA ###
Array
(
  [type] => 2
  [message] => mysqli::query() [<a href='mysqli.query'>mysqli.query</a>]: Error reading result set's header
  [file] => /...path.../myPhpScript.php
  [line] => 123
)

### REQUEST DATA ###
Array
(
  [data1] => ABC123
  [data2] => DEF456
  [sessionid] => c1396f33b517267ae29a21eb5f12336f
)