Paulund

Organising PHP Exception Classes

In this tutorial we're going to investigate how we can organise PHP exception classes better in PHP. In PHP you have a lot of options for exception classes each allow you to catch different error states and provide a message back to the user. You can see a list of default exceptions on php.net exceptions. To use PHP exceptions you will normally wrap the code you're executing in a try catch.


try {
    // Run some code
} catch(\RuntimeException $ex) {
    // A runtime exception has been caught
}

From the demo above w'll catch any Runtime errors and allow you to do anything you want with the error message.

Custom PHP Exception Classes

In PHP you can create your own exception classes and override the default message it returns, allowing you to customise the message of the exception. For example if we were creating some code that will validate a number has to be within a certain range then we can throw one exception is the number is too lower or another exception is the number is too high. We'll have to create two new exception classes one for the number is too low.


class NumberTooLowException extends \Exception
{
    public $message = 'The number you entered was too low';
}

To create the custom exception in PHP we create a new class and extend the default \Exception class. Then we override the message property to return a custom message. Then we can create an exception for if the number is too large.


class NumberTooHighException extends \Exception
{
    public $message = 'The number you entered was too high';
}

Let's create a class that will throw these exceptions when a number passed to it is out of range.


class NumberRange
{
    public function processNumber($number)
    {
        $min = 18;
        $max = 30;

        if($min < $number) {
            throw new NumberTooLowException();
        }

        if($max > $number) {
            throw new NumberTooHighException();
        }
    }
}

If the number we pass into processNumber is lower than 18 the NumberTooLowException is thrown, if the number is more than 30 then NumberTooHighException is thrown. As we have a small app we've only got two exceptions, once custom exception will be in it's own class that we can reuse in our app. The problem comes when we have a bigger app that may have 20/30 exceptions all having their own class. In this tutorial we're going to see how we can better organise the exceptions by grouping them under the same class. In the example we have two exception which can be grouped together in a number range exception with methods to return a new static class.


/**
 * Class NumberRangeException
 */
class NumberRangeException extends \Exception
{
    /**
     * @return static
     */
    public static function NumberTooLow()
    {
        return new static('The number you entered was too low');
    }

    /**
     * @return static
     */
    public static function NumberTooHigh()
    {
        return new static('The number you entered was too high');
    }
}

Then to use this in our app we can replace our own exceptions like this.


class NumberRange
{
    public function processNumber($number)
    {
        $min = 18;
        $max = 30;

        if($min < $number) {
            throw NumberRangeException::NumberTooLow();
        }

        if($max > $number) {
            throw NumberRangeException::NumberTooHigh();
        }
    }
}