Creating Exception types on-the-fly in modern PHP

Written by Matthew Weier o'Phinney - - Aggregated on Wednesday December 5, 2018

We pioneered a pattern for exception handling for Zend Framework back as we initially began development on version 2 around seven years ago. The pattern looks like this:

What this gave users was the ability to catch in three ways:

So, as an example:

try {
    $do->something();
} catch (MostSpecificException $e) {
} catch (PackageLevelExceptionInterface $e) {
} catch (\RuntimeException $e) {
}

This kind of granularity is really nice to work with. So nice that some standards produced by PHP-FIG now ship them, such as PSR-11, which ships a ContainerExceptionInterface and a NotFoundExceptionInterface.

One thing we've started doing recently as we make packages support only PHP 7 versions is to have the marker ExceptionInterface extend the Throwable interface; this ensures that implementations must be able to be thrown!

So, what happens when you're writing a one-off implementation of something that is expected to throw an exception matching one of these interfaces?

Why, use an anonymous class, of course!

As an example, I was writing up some documentation that illustrated a custom ContainerInterface implementation today, and realized I needed to throw an exception at one point, specifically a Psr\Container\NotFoundExceptionInterface. I wrote up the following snippet:

$message = sprintf(/* ... */);
throw new class($message) extends RuntimeException implements
    NotFoundExceptionInterface {
};

Done!

This works because RuntimeException takes a message as the first constructor argument; by extending that class, I gain that behavior. Since NotFoundExceptionInterface is a marker interface, I did not need to add any additional behavior, so this inline example works out-of-the-box.

What else are you using anonymous classes for?

Creating Exception types on-the-fly in modern PHP was originally published 5 December 2018 on https://mwop.net by Matthew Weier O'Phinney.

« User Notifications - Laracasts

Symfony blog - Symfony 2.8.49 released »