Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused by this PHP Exception try..catch nesting

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 MyException

But instead it outputs:

throwing AnotherException
caught AnotherException
throwing MyException
caught Exception

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

Thanks.

like image 558
Dom M. Avatar asked Apr 06 '10 16:04

Dom M.


2 Answers

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.

like image 85
Oddthinking Avatar answered Oct 01 '22 05:10

Oddthinking


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.

like image 30
thetaiko Avatar answered Oct 01 '22 04:10

thetaiko