How to log PHP errors and warnings into a file
Dennis Maina
Dennis Maina

Published on 11th August, 2022 (1 year ago) ● Updated on 11th August, 2022

How to log PHP errors and warnings into a file

(4 minutes read)

When writing server-side code in PHP, it's always a good practice to consider security first. When dealing with PHP errors that could occur at runtime, it's advisable to hide these error messages from the users and instead log them into a file for developers or system admins to review them. This is a good security practice as the error messages can expose an existing vulnerability or give an attacker an entry point into your system.

Enough of talking, how can we do that effectively and efficiently?

We are going to create a class that's going to be invoked every time an error occurs in the system.

  • If you are using an MVC place this code at the top of your main index file.
  • If you are not using an MVC, place this code at the top of every PHP file that you want the errors handled.
include('.php');
if (ERR_HANDLER_ENABLED) { 
    register_shutdown_function('sysFatalErr'); 
    set_error_handler('sysErrorhandler'); 
}

This class collects all the errors reported from a PHP script, classifies them as either general errors or fatal errors. After classification, it passes the error to the respective method which then calls the log function that writes them out.

Let's define some constant variables here.

/**
 * if your error class file resides in a folder called classes and the index file is in the base folder use:
 *
 * define('ERR_HANDLER_PATH', substr(dirname(__file__), 0, strpos(dirname(__file__), 'classes') - 1) . '/'); // DO NOT change!!
 * 
 * after using the above line comment or remove the fisrt line down here
**/
define('ERR_HANDLER_PATH', dirname(__file__).'/'); // DO NOT change!!
define('ERR_HANDLER_LOG_FOLDER', 'logs'); // Name of logs folder.. Create if it does not exist.
define('ERR_HANDLER_ENABLED', 1); // Enable custom error handler?
define('ERR_HANDLER_DISPLAY', 1); // Display a message on screen?
define('ERR_APPEND_RAND_STRING', 0); // Adds random string to file name for security. Prevents someone attempting browser access.
define('MASK_FILE_PATH', 0); // Hide file path if error occurs..
define('FILE_ERR_LOG_FILE', 'errors.log'); // File name of error log
define('FILE_FATAL_ERR_LOG_FILE', 'fatal_errors.log'); // File name of fatal error log

We create our class which has four functions and each function calls the log function when invoked:

  • generalErr - This function is invoked when a general error occurs.
  • mailErr - This function is invoked when an email error occurs.(if you have an email sending script)
  • fataErr - This function is invoked when a fatal error occurs and no further execution can happen.
  • log - calls the write function which then writes the error into a file.
class Errs {

  public function generalErr($error) {
    Errs::log($error, FILE_ERR_LOG_FILE);
  }

  public function mailErr($error) {
    Errs::log($error, FILE_ERR_LOG_FILE);
  }

  public function fatalErr($error) {
    Errs::log($error, FILE_FATAL_ERR_LOG_FILE);
  }

  public function log($error, $file) {
    if (is_dir(ERR_HANDLER_PATH . ERR_HANDLER_LOG_FOLDER)) {
      write(ERR_HANDLER_PATH . ERR_HANDLER_LOG_FOLDER . '/' . Errs::raStr() . $file, trim($error) . linending() . '***** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - *****' . linending());
    }
  }

  public function raStr() {
    return (ERR_APPEND_RAND_STRING ? substr(md5(uniqid(rand(),1)), 3, 30) . '-' : '');
  }


}

// Initiate the class..
$DDEH = new Errs();

Now we check to see if the error handler is enabled. If it is enabled, we turn of displaying all the errors to the user.

 

if (ERR_HANDLER_ENABLED) {
  // Switch off display errors
  @ini_set('display_errors', 0);
  // Set error reporting level..
  error_reporting(E_ALL);
}

 

On the Error reporting levels, we're going to be using E_ALL. PHP provides lots of them which you can look at here PHP Error Levels.
Here's just a few that I think are useful together with their error codes.

 

 

TIP: Passing a value of (-1) to the error_reporting() function will show every possible error when new levels and constants are added in future PHP versions.

Now, we create a function that inserts a newline depending on the OS architecture.

function linending() {
  $newline = "\r\n";
  if (isset($_SERVER["HTTP_USER_AGENT"]) && strstr(strtolower($_SERVER["HTTP_USER_AGENT"]), 'win')) {
    $newline = "\r\n";
  } else if (isset($_SERVER["HTTP_USER_AGENT"]) && strstr(strtolower($_SERVER["HTTP_USER_AGENT"]), 'mac')) {
    $newline = "\r";
  } else {
    $newline = "\n";
  }
  return (defined('PHP_EOL') ? PHP_EOL : $newline);
}

This function will be called whenever a fatal error occurs.

function sysFatalErr() {
  global $DDEH;
  $error = error_get_last();
  if (isset($error['type'])) {
    if ((defined('E_ERROR') && $error['type'] == E_ERROR) || $error['type'] == 4) {
      $string = '[Error Code: ' . $error['type'] . '] ' . $error['message'] . linending();
      $string .= '[Date/Time: ' . date('j F Y @ H:iA') . ']' . linending();
      $string .= '[Fatal error on line ' . $error['line'] . ' in file ' . $error['file'] . ']';
      if (ERR_HANDLER_DISPLAY) {
        echo 'Finally, we write out our errors into a file. Remember to have the logs folder created.
function write($file, $data) {
  file_put_contents($file, $data, FILE_APPEND);
}

You can get the whole code on the GitHub repo Here

In need of a developer for a project? Hit me Up DentriceDev Solutions

Happy Coding.


Comments (0)

Dennis Maina

Dennis Maina

https://dentricedev.com

CEO and Founder of DentriceDev Solutions.

24

Articles

July '22

Joined date

Domain Name Registration & Hosting
Domain Name Registration & Hosting

HostPinnacle Kenya is the best and cheapest web hosting company in Kenya with world-class web hosting packages and affordable web design offers. Apart from that we offer free life-time SSL certificate, affordable domain registration in Kenya and free whois privacy. We have an award-winning support team available 24/7/365 to help you with your queries.

Ready to Elevate Your Digital Presence?
Ready to Elevate Your Digital Presence?

Whether you're looking to launch a cutting-edge mobile app, revamp your website with sustainable web design, or harness the power of AI and digital marketing to outshine your competition, we're here to turn your vision into reality. At DentriceDev, we blend innovation, expertise, and passion to deliver digital solutions that drive results. Don't let your business get left behind in the digital revolution. Reach out to us today, and let's create something remarkable together. Connect with us directly at [email protected], give us a call or WhatsApp at +254 757 927190, or simply fill out our contact form to get started. Your digital future awaits, and we're excited to be part of your journey!

Do you want to write with us? Register and start blogging.

Register Login

Thank you for your support!

We deliver the best web products