Home > front end >  Reverse Cascade in PHP Exception Classes?
Reverse Cascade in PHP Exception Classes?

Time:04-30

I just wanted to double-check if what I just found is default PHP behaviour, because I cannot explain it otherwise. Say you build a custom PHP Exceptions class:

<?php
namespace XYZ;

if ( ! class_exists( 'XYZ\CustomException' ) ) {

  class CustomException extends \Exception {

    public function __construct( int $code ) {

        parent::__construct( "The error code is: $code", $code );

    }

  }

}
?>

You then launch a PHP script with a content like:

try {
  throw new CustomException(1);
} catch ( \Exception $e ) {
  echo "regular exception thrown";
} catch ( CustomException $e ) {
  echo "custom exception thrown";
}

When running that block, I get "regular exception thrown".

When I reverse the catch blocks of the script to:

try {
  throw new CustomException(1);
} catch ( CustomException $e ) {
  echo "custom exception thrown";
} catch ( \Exception $e ) {
  echo "regular exception thrown";
} 

I get "custom exception thrown".

Is it actually default in PHP that child classes of the Exception class will be caught by the parent Exception handler, if the parent Exception class catch block is written first?? Or is this some sort of weird config that is unusual?

CodePudding user response:

When an exception is thrown, it goes through the try blocks in order, testing whether the exception is an instance of the specified class, and it stops when it gets to the first matching block. Since CustomException is a subclass of Exception, the catch ( \Exception ) block matches this test, so it stops there first.

It's essentially like:

if (is_a($e, 'Exception')) {
    echo "regular exception thrown";
} elseif (is_a($e, 'CustomException')) {
    echo "custom exception thrown";
}

It doesn't try to find the catch block with the closest match, it's just done sequentially. It's your responsibility to order them by specificity.

The documentation explains this:

The first catch block a thrown exception or error encounters that matches the type of the thrown object will handle the object.

CodePudding user response:

That is normal behavior. Since your CustomException is inheriting Exception and your first catch is against Exception it will stop here first.

  • Related