in Best Practices

Using Interfaces For Exceptions

In PHP (as well as many other object oriented languages), exceptions are simply objects, which can be extended and reused. PHP makes them special in the sense that only exceptions that inherit from the base class Exception are throwable by the interpreter (you cannot throw any generic object you create).

Most developers are therefore aware of the ability to extend exceptions, thus giving them unique, typehintable values that can be identified, caught and handled.

<?php

class MyException extends Exception {}
    
try {
    // some code here
    throw new MyException('exception message');
} catch (MyException $e) {
    // handle exception here
}

?>

Using interfaces for exceptions

PHP has a number of drawbacks in terms of extending the base exception class, namely that you cannot extend multiple classes at the same time. For example, you cannot extend both Exception and MyException in a class; this is not possible. PHP seeks to address some of these problems with the introduction of traits, but traits are not typehintable.

However, interfaces provide us an opportunity to create exceptions that share multiple different groups of problems. For example:

<?php

interface NotCountableException {}
interface NotIterableException {}
    
class NotUsableException extends Exception 
    implements NotCountableException, NotIterableException {}

try {
    // If it's not countable we raise the not usable exception
    throw new NotUsableException('not countable');
} catch (NotCountableException $e) {
    // we can handle the exception
}

?>

This is also useful in library code, when you want to have a base exception type that applies to all exceptions for a particular library. By implementing the exception interface, you can typehint on that interface no matter the inheritance chain for the actual exception.

The benefit of interfaces over inheritance

It might seem unusual to use an interface for exceptions; after all, exceptions are raised for specific kinds of errors. But exception classes are meant to be specific (e.g. class RecordNotFoundInDatabase), while interfaces provide flexibility to identify generic exception types (interface DatabaseError). By being able to group the exception types by interface, without having a long inheritance chain, it allows for the inclusion of multiple types when necessary, and greater flexibility in code. Since you cannot remove a particular parent class from the inheritance chain (but you can remove an interface from your own implementation should you so desire), this increases flexibility.

This is also useful in code that is meant to be reused like library code. The base exception in Ralph Schindler’s article is one example; another example is providing different interface types for developers to implement in their own exceptions when extending or implementing the library. By providing base exception interfaces as well as collection interfaces, you increase the re-usability of your code.

For an in-depth analysis of exception handling in object oriented PHP, as well as other great object oriented PHP topics, check out Mastering Object Oriented PHP.

Be the first to get Modern Object-Oriented PHP!

Long to learn how you can develop modern applications using object-oriented PHP? Curious about how to apply all these best practices to your code?

Modern Object-Oriented PHP is a brand-new book focused on teaching you the techniques you need for writing modern, well-designed object-oriented applications!

The book lands in April. Sign up today for a sample chapter plus special launch day discounts!

Powered by ConvertKit
  1. Hi,

    Its a nice idea to use interfaces to grouping exceptions. With this concept, its easier to understand some parts of the code, so it might be increase the readability too.

    Thanks for the post

  2. Thanks very much, very useful, easy to understand and put into motion!

Comments are closed.