开发者

Confused by this PHP Exception try..catch nesting

开发者 https://www.devze.com 2022-12-26 09:56 出处:网络
I\'m confused by the following code: class MyException extends Exception {} class AnotherException extends MyException {}

I'm confused by the following code:

class MyException extends Exception {}
class AnotherException extends MyException {}

class Foo {
  public function something() {
    print "throwing AnotherException\n";
    throw new AnotherException();
  }
  public function somethingElse() {
    print "throwing MyException\n";
    throw new MyException();
  }
}

$a = new Foo();

try {
  try {
    $a->something();    

  } catch(AnotherException $e) {
    print "caught AnotherException\n";
    $a->somethingElse();    
  } catch(MyException $e) {
    print "caught MyException\n";
  }
} catch(Exception $e) {
  print "caught Exception\n";
}

I would expect this to output:

throwing AnotherException
caught AnotherException
throwing MyException
caught MyEx开发者_运维问答ception

But instead it outputs:

throwing AnotherException
caught AnotherException
throwing MyException
caught Exception

Could anyone explain why it "skips over" catch(MyException $e) ?

Thanks.


The exception handlers catch exception raised by code inside the scope of their try block.

The call to $a->somethingElse() does NOT occur within the try block associated with the skipped exception handler. It occurs within another catch clause.

Just because it appears physically below the line that raises the exception isn't enough to make it cover that code.

The style choice of indenting braces makes this less clear, IMHO. The close brace for the previous try block appears on the same line as the next catch, even though they are unrelated (well, sibling) scopes.


Only because there isn't enough room for this in a comment. Think of the try...catch as an if...else loop. You wouldn't expect the following:

$a = 10;
if($a == 9)
    print "\$a == 9";
elseif($a == 10) {
    $a = 11;
    echo "now \$a == 11";
} elseif($a == 11) {
    echo "\$a == 11";
}

to print out the last condition ("\$a == 11"), because the condition was already met by the first elseif. The same is true with the try...catch. If the condition is met, it doesn't continue searching for new conditions in the same scope.


I am not sure if following is legal ("try"ing inside a catch block), but does give expected output:

class MyException extends Exception {}
class AnotherException extends MyException {}

class Foo {
  public function something() {
    print "throwing AnotherException\n";
    throw new AnotherException();
  }
  public function somethingElse() {
    print "throwing MyException\n";
    throw new MyException();
  }
}

$a = new Foo();

try {
   try {
      $a->something();
   } catch(AnotherException $e) {
       print "caught AnotherException\n";
       try{
          $a->somethingElse();
       } catch(MyException $e) {
          print "caught MyException\n";
       }
   }
} catch(Exception $e) {
  print "caught Exception\n";
}

Gives output:

throwing AnotherException
caught AnotherException
throwing MyException
caught MyException


Not sure if this has been considered answered or not, but the answer is even simpler than what has been posed here. For every try, only ONE catch block can be triggered and it will always be the most specific one applicable.

In this case, AnotherException is thrown and handled by the first catch block of the inner try/catch, so it won't be handled by the second catch block. The new exception thrown in the catch block get's handled by the outer try/catch.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号