PHP Errors & Exception Handling Tutorial

In this tutorial we learn how to handle errors with PHP's built-in error reporting, custom error handlers, and the die() function.

We also learn how to handle exceptions with the try/catch/finally block and the throw keyword.

What is an error?

When a piece of code returns an unexpected result or stops abruptly, the interpreter will raise an error.

Raising an error is simply a term for stopping the execution of the program and displaying the appropriate error.

PHP provides us with multiple ways to handle errors:

  • Built-in error reporting
  • The die() function
  • Custom error handlers

How to use PHP's built-in error reporting

PHP provides a default error reporting mechanism to gracefully handle errors in the code and provide a better experience to the end user.

We can use error_reporting() function to set which errors to show and which errors to hide.

Syntax:
 error_reporting(REPORTING_LEVEL);

The following table lists all the arguments available for the error_reporting() function:

Reporting LevelDescription
E_WARNINGOnly displays warning messages and doesn't stop the execution of the script.
E_NOTICEDisplays notice that occur during normal code execution.
E_USER_ERRORDisplay user generated errors i.e the custom error handlers.
E_USER_WARNINGDisplay user generated warning messages.
E_USER_NOTICEDisplay user generated notices.
E_RECOVERABLE_ERRORDisplays non-fatal errors.
E_ALLDisplay all errors and warnings.

If we do not provide any value for the function, the interpreter will use E_ALL.

Example: change error reporting level
<?php

error_reporting(E_NOTICE);

?>

How to report an error with the die() function

The die() function is used to display any message and stop execution of the current script at the same time.

Syntax:
// code to error report
or die("Error message");
Example: non-existent file
<?php

fopen("fileThatDoesntExist.txt", "r")
or die("Execution stopped: Unable to open file<br>");

echo "Interpreter does not reach this statement.";

?>

In the example above, we try to open a file that doesn’t exist. We specify that if the function doesn’t open the file, the program should stop execution and display an error message.

*Even though the or die() statement is usually on its own line, the statement that it checks is not terminated with a semicolon.

How to create custom error handlers

PHP allows us to use a custom method to display an error message, or execute any code, when an error occurs. We have to set our custom method as the default error handler using the function set_error_handler() .

Syntax:
function customErrorMethod($error_no, $error_msg) {

}

set_error_handler("customErrorMethod");

The $error_no and $error_msg parameters are required in the function, even if we don’t use them. The name of the custom error method must also be wrapped in quotes.

Example: division by zero custom error handler
<?php

function customErrorMethod($error_no, $error_msg) {
    echo "<p>A wild error appears!<br>";
    echo "Error: " . $error_msg ."<br>";
    echo "Our developer team has been notified. Thank you for your patience.</p>";
}

set_error_handler("customErrorMethod");

// Will raise error
$result = 2/0;

?>

How to handle exceptions

Normally, when an error occurs, the code execution is stopped and a message is displayed on the screen.

Exception handling is a way to handle those errors, but redirect the flow of execution when an error occurs.

PHP provides us with a few ways to handle exceptions:

  • throw keyword
  • try/catch/finally block
  • Overriding the Exception class

How to throw an exception

We can manually force an exception by using the throw keyword in conjunction with the Exception class.

Because Exception is a class, we need to create a new object and then use the throw keyword to force the exception.

Syntax:
 throw new Exception("Exception message");

The object of the Exception class does not need to be stored because it’s only used temporarily. The garbage collector will pick it up afterwards.

Example:
<?php

throw new Exception("Manually forcing exception");

echo "Cannot reach this statement";

?>

In the example above, we manually force a new exception. When an exception is thrown, the code following it will not be executed, and the interpreter will try to find the matching catch block.

If the exception is not caught in the catch block, the interpreter will raise an Uncaught Exception error.

The example above has no catch block so the interpreter will raise such an error.

Output:
 Fatal error: Uncaught Exception: Manually forcing exception

How to handle an exception with try, throw and catch

To avoid the Uncaught Exception error, we need to create a try/catch block.

Syntax:
try {

    // try to execute this code, if not
    throw new Exception();

} catch(Exception $exceptionObject) {

    // if any exceptions occur
    // catch the exception being thrown

}

We place any code that we want to test inside the try code block. If an error is raised by the code, we throw an exception.

The catch block will handle that error and the error will be stored in the $exceptionObject to work with.

Example:
<?php

try {

    // simulate an error
    if(1 == 1) {
        // if the error occurs, throw the exception
        throw new Exception("Error thrown in try block");
    }

} catch(Exception $e) {

    // catch the exception (if any) into
    // the exception object $e
    echo $e;
}

?>

In the example above, we simulate an error in the try block and throw an exception.

When the interpreter sees that an exception is thrown, it will find the catch block and execute any code within it.

In the example above, we simply print the error stored in $e to the page.

Output:
 Exception: Error thrown in try block

Every exception that is thrown must have a catch block to catch it.

How to handle multiple exceptions

We know that every throw must have a catch. To handle multiple throws, we simply add multiple catch blocks.

Syntax:
try {

    // try to execute this code, if not
    throw new Exception();

    // more code to try and execute, if not
    throw new Exception();

} catch(Exception $exceptionObject1) {

    // if the first exception is thrown
    // catch and handle it here

} catch(Exception $exceptionObject2) {

    // if the second exception is thrown
    // catch and handle it here

}
Example: multiple catch blocks
<?php

try {

    // simulate an error
    if(1 != 1) {
        // error does not occur so the
        // exception isn't thrown
        throw new Exception("Error1");
    } else {
        // this error does occur so its
        // exception is thrown
        throw new Exception("Error2");
    }

} catch(Exception $e1) {

    // handle exception (if any) from
    // the if block. The first possible
    // exception
    echo $e1;

} catch(Exception $e2) {

    // handle exception (if any) from
    // the else block. The second possible
    // exception
    echo $e2;
}

?>

In the example above, the first error in the try block isn’t thrown, but the second one is. Because the first exception isn’t thrown, the first catch block isn’t executed.

The second exception is thrown, so the second catch block is executed which simply prints the exception message to the page.

Output:
 Exception: Error2

How to use the finally block

PHP allows us to specify a finally block after, or instead of, catch blocks.

Code inside the finally block will always be executed after the try/catch blocks, regardless of whether an exception was thrown.

This is useful when we need to do any clean up operations like closing a database connection or a file.

Syntax:
try {

    // try to execute this code, if not
    throw new Exception();

    // more code to try and execute, if not
    throw new Exception();

} catch(Exception $exceptionObject1) {

    // if the first exception is thrown
    // catch and handle it here

} catch(Exception $exceptionObject2) {

    // if the second exception is thrown
    // catch and handle it here

} finally {

    // this code always executes

}
Example: finally block
<?php

try {

    // simulate an error
    if(1 != 1) {
        // error does not occur so the
        // exception isn't thrown
        throw new Exception("Error1");
    } else {
        // this error does occur so its
        // exception is thrown
        throw new Exception("Error2");
    }

} catch(Exception $e1) {

    // handle exception (if any) from
    // the if block. The first possible
    // exception
    echo $e1;

} catch(Exception $e2) {

    // handle exception (if any) from
    // the else block. The second possible
    // exception
    echo $e2;

} finally {

    echo "<p>This code will always execute regardless of any exceptions thrown or not.</p>";

}

?>

In the example above, we throw an error that is handled in the second catch block.

In the finally block we print a simple statement to the page to demonstrate that any code in the block will always execute.

How to create a custom exception class

To create our own custom exception class we have to inherit from the Exception parent class. We can then use or override its methods or create our own custom methods.

Example: custom exception class
<?php

// custom exception class
class customException extends Exception {

    function customErrorMessage() {
        return "<p>Custom error on line " . $this->getLine() . " in " . $this->getFile() . "</p>";
    }

}

try {
    // simulate error
    if(true) {
        throw new customException();
    }

} catch(customException $e2) {

    echo $e2->customErrorMessage();

}

?>

In the example above, we inherit from the Exception class and create our own error message method.

Once the exception is thrown in the try block, we can use the customErrorMessage() method in the catch block to handle it.

The getLine() and getFile() methods are methods inside the Exception parent class that we have access to.

Summary: Points to remember

  • PHP’s built-in error reporting mechanism allows us to gracefully handle error in our code.
  • The die() function will stop a script from executing when it encounters an error.
  • We can create our own error reporting function and set it as default with the set_error_handler() function.
  • Exception handling does not stop the flow of our application, but instead redirects it with the try/catch/finally block.
  • Exceptions are raised with the throw keyword in combination with the try/catch/finally block.
  • We can create our own custom exception class by inheriting from the Exception parent class.