Creating Exception types on-the-fly in modern PHP - Matthew Weier O'Phin...
source link: https://www.tuicool.com/articles/hit/veeimaf
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
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:
- We would create a marker
ExceptionInterface
for each package. - We would extend SPL exceptions and implement the package marker interface when doing so.
What this gave users was the ability to catch in three ways:
- They could catch the most specific exception type by class name.
- They could catch all package-level exceptions using the marker interface.
- The could catch general exceptions using the associated SPL type.
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?
Posted by Matthew Weier O'Phinney ,
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK