Lessons in PHP: Show Errors and Error Handling

Php Show Errors

PHP is the most popular server-side web programming language today, so it’s important to know how to resolve any errors that may occur when your PHP code is executed.

In this article, we will look at the basics of how to do error handling in PHP, using the built-in functions, writing custom error handler functions, and with Exception error handling.

The Types of Errors in PHP

There are two fundamental types of errors in software:

  • Internal Errors: These are the logic errors in your code. These errors can be prevented to a very large degree by careful programming.
  • External Errors: These are errors related to the interactions with the world outside your code (e.g., failing to opening a file or database, the network connection dropping, being unable to load a certain PHP module, etc.). These errors will always occur, but their impact can be mitigated. The better you prepare your code for these external errors, by assuming as little as possible when your code is executing, the less these errors will negatively affect your program.

Ways to Deal with PHP Errors

Once errors occur and we detect them, there are four fundamental ways to deal with them:

  • Display the Error: This allows the error to be shown to the developer and/or user when the program is being executed.
  • Log the Error: This allow the errors to be stored and reviewed from a textual log file.
  • Act on the Error: The type of action needed will be different for each program situation.
  • Ignore the Error: This should always be avoided.

In this article, we will focus on the displaying, logging, and handling of errors. Once you know how to handle errors, you can act on them easily.

Showing Errors and Error Reporting Settings

Depending on if we are running code in production or in development, we might want to turn on or off reporting certain types of errors.

There are different locations where we can control what error types are to be reported:

  • In the php.ini file
  • In the .htaccess file on your web server
  • From your own PHP code.

A full description of the PHP error configuration values can be found here. These are the most relevant options with their default value:

Options for Showing PHP Errors

There are four possible options for showing PHP errors:

  • error_reporting: Set the error reporting level. The default value is: “E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED,” meaning this setting does not show E_NOTICE, E_STRICT and E_DEPRECATED level errors.
  • display_errors: Set it to “ON” (default is “OFF”)if errors are to be printed to the screen.
  • log_errors: This indicates whether or not error logging should be done; default value is “on.”
  • error_log string: Sets the name of the file where script errors should be logged

Let’s see how we can use these configuration options.

During development, we might want to turn all error reporting from the php.ini:

display_errors = on
error_reporting = E_ALL

We could do the same from our PHP code during runtime by calling the error_reporting() function:

error_reporting(E_ALL);

To turn on error logging and log the errors to our own specific log file (instead of the default error log file, which is often the web server error log file or the syslog file), we could configure PHP with:

log_errors = on
error_log = "/tmp/php-error.log"

You can now log errors via your PHP code:

error_log( "This code has errors!" );

Built-In Error Levels

PHP currently has 15 predefined error constants, each with their own identifying (bitmask) number. These are built-in error types that PHP or you, the developer, can trigger when an error occurs. You can decide which error types you want reported, as we will see in the next section.

These are the built-in PHP error types:

Type Description
E_ERROR Fatal run-time errors
E_WARNING Run-time warnings (non-fatal errors)
E_PARSE Compile-time parse errors
E_NOTICE Run-time notices
E_CORE_ERROR Fatal errors that occur during PHP’s initial startup
E_CORE_WARNING Warnings (non-fatal errors) that occur during PHP’s initial startup
E_COMPILE_ERROR Fatal compile-time errors
E_COMPILE_WARNING Compile-time warnings (non-fatal errors)
E_USER_ERROR User-generated error message
E_USER_WARNING User-generated warning message
E_USER_NOTICE User-generated notice message
E_STRICT Enable to have PHP suggest changes to your code that will ensure the best interoperability and forward compatibility of your code
E_RECOVERABLE_ERROR Catchable fatal error
E_DEPRECATED Run-time notices
E_USER_DEPRECATED User-generated warning message
E_ALL All errors and warnings, as supported

Here are some code examples of these error constants being triggered:

// E_ERROR
nonExistingFunction(); 

// E_WARNING
$fh = fopen('none-existing-file', 'r');

// E_NOTICE
$x = $y + 5; // $y was not defined

// E_USER_ERROR
if ($divisor == 0) {
    trigger_error("Cannot divide by zero", E_USER_ERROR); // error triggered by the developer
}

Creating Custom Error Handlers

Now that we can configure PHP to tell it what types of errors to report on, we need to be able to handle different error types in our own way. Just displaying standard PHP error messages is often not good enough.

We want to handle the error and display our own messages when an error happens. For this, we can use the set_error_handler() function.

Here is a very simple custom error handling function:

// error handler function
function errorHandler($errno, $errstr) {
  echo "Error: [$errno] $errstr";
}

// set error handler
set_error_handler("errorHandler");

// trigger an error
echo($foo); // undefined variable!

So when an error occurs, the custom error handler function is called with an error-number argument and an error-string argument. These two arguments are passed from the set_error_handler() call to our function.

There are more arguments we could use, as we will soon see, but the output of running this code would be:

Error: [8] Undefined variable: foo

Let’s see what a slightly less simple custom error handling function could look like. This error handler should be able to detect the error types and decide what action to take and/or what error message to show.

function errorHandler($errno, $errstr, $errfile, $errline) {

    switch ($errno) {
        case E_NOTICE:
        case E_USER_NOTICE:
        case E_DEPRECATED:
        case E_USER_DEPRECATED:
        case E_STRICT:
            echo("STRICT error $errstr at $errfile:$errline n");
            break;

        case E_WARNING:
        case E_USER_WARNING:
            echo("WARNING error $errstr at $errfile:$errline n");
            break;

        case E_ERROR:
        case E_USER_ERROR:
        case E_RECOVERABLE_ERROR:
            exit("FATAL error $errstr at $errfile:$errline n");

        default:
            exit("Unknown error at $errfile:$errline n");
    }
}

set_error_handler("errorHandler");

$foo = false;

if (! $foo) {
   trigger_error('Value $foo must be true', E_USER_NOTICE);
}

Note how we are grouping the handling of certain error types using the fall-through functionality of the switch-case statements.

The output would be something like:

STRICT error Value $foo must true at /tmp/test.php:32

Now you can handle types of errors differently (or the same) and show custom error message, too. Of course, a real custom error handling function should be able to do much more with errors and possibly act upon them in a specific and sensible way.

It is important to keep your custom error handling function simple and robust to ensure no errors occur within this function itself, as those would not get reported. There are several PHP libraries that can help you with creating more advanced error handling.

Using PHP Exceptions

PHP version 5 introduced another way of handling errors: Exceptions.

Exception handling is used to change the normal flow of a running program if a specified error condition occurs. It’s a more language-syntax-integrated way of doing error handling than writing custom error handling functions.

Exceptions are represented in PHP by the class Exception. Exceptions are raised using the “throw” syntax and can be caught using a “try/catch” syntax block. Any code in which an Eexception error may occur should be placed in the “try” block, which can be followed by a “catch” block to handle the error. As the thrown Exceptions bubble up the code stack, they can also be handled by other “catch” blocks in your code.

This is what the Exception syntax looks like:

try { // throw errors in the try-block

    // if an error occurs we can throw an exception
    throw new Exception('this is an error.');

}
catch(Exception $e) { // catch the throws in the catch-block

    // do something with the exception object, eg. display its message
    echo 'Error message: ' .$e->getMessage();

}

Which would output:

Error message: this is an error.

After an Exception object is thrown, we can access these member functions:

  • getMessage() gets the Exception message
  • getPrevious() returns previous Exception
  • getCode() gets the Exception code
  • getFile() gets the file in which the Exception occurred
  • getLine() gets the line in which the Exception occurred
  • getTrace() gets the stack trace
  • getTraceAsString() gets the stack trace as a string
  • __toString() is a string representation of the Exception
  • __clone() clones the Exception

Here is another example of Exception handling:

$file = '/tmp/foo.txt';

try {
    // check if the file exists and is writable
    if (! file_exists($file)  || ! is_writable($file) ) {

        // if not: throw an exception
        throw new Exception('File ' .$file. ' not found or is not writable.');

        echo('will the code get here?'); // not if an exception was thrown before
    }
}
catch(Exception $e) {
    echo 'Error message: ' .$e->getMessage();
    return false;
}

If you run this code without creating the file first, you will see this error:

Error message: File /tmp/foo.txt not found or is not writable.

Exceptions bubble up the code stack, so we can have multiple throw statements in different code blocks and still handle them gracefully. However, any Exceptions that are thrown but not caught will generate an E_FATAL error with the message “Uncaught Exception.”

An example:

$foo = 10;

try {
    if( is_numeric($foo) ){
        if ($foo > 5){
            throw new Exception('number too high'); // this will be thrown
        }
    }
    else {
        throw new Exception('not a number type');
    }
}
catch(Exception $e) {
    echo 'Error message: ' .$e->getMessage() . ' at line: ' . $e->getLine();
    //return false;
}

Note that we called the “$e->getLine()” member function of the Exception object to get the line number when the Exception was thrown.

It is possible to nest multiple try-throw-catch blocks within each other. This allows you to specify what Exception error is handled where (in a clean and simple way) at the point in your code where it makes the most sense. Just remember to always put any code that throws within a “try” block.

Custom Exception Handlers

So far we have been using the built-in Exception class, but we also can write our own custom Exception handler by extending the built-in Exception class. This is useful when we want to override the built-in member functions or add new member functions. You can see several in-depth code examples here.

Difference Between Standard Errors and Exceptions

Standard error handling is the older way of handling errors in PHP. Exception handling is only available from PHP 5 onward and requires using an object-oriented programming structure.

Both can be used alongside each other. In fact, any Exception that is thrown but not caught will eventually generate an E_FATAL error with the message “Uncaught Exception.”

With the set_error_handler() function code example shown below, we could even handle all standard errors as an Exception:

set_error_handler(function ($errno, $errstr, $errfile, $errline ) {
    if (error_reporting()) {
        throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    }
});

try {
    // E_WARNING
    $fh = fopen('none-existing-file', 'r');
}
catch(Exception $e) {
    echo 'Error message: ' .$e->getMessage();
    return false;
}

Final Word

I hope this quick introduction into PHP error handling has helped yield your understanding of this important part of development. You should now know how to display and log errors and handle them in the various ways PHP makes it possible, either with a custom error handling function or by Exception handling.