Путать это исключение PHP try..catch nesting - PullRequest
13 голосов
/ 06 апреля 2010

Меня смущает следующий код:

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";
}

Я бы ожидал, что это выведет:

throwing AnotherException
caught AnotherException
throwing MyException
caught MyException

Но вместо этого он выдаст:

throwing AnotherException
caught AnotherException
throwing MyException
caught Exception

Может ли кто-нибудь объяснить, почему он «пропускает» улов (MyException $ e)?

Спасибо.

Ответы [ 4 ]

16 голосов
/ 06 апреля 2010

Обработчики исключений перехватывают исключение, созданное кодом внутри области их блока try.

Вызов $a->somethingElse() НЕ происходит в блоке try, связанном с обработчиком пропущенных исключений. Это происходит в другом предложении catch.

Только потому, что оно физически появляется ниже строки, которая вызывает исключение, недостаточно для того, чтобы охватить этот код.

Выбор стиля фигурных скобок делает это менее понятным, ИМХО. Закрывающая фигурная скобка для предыдущего блока try появляется в той же строке, что и следующий улов, даже если они не связаны (ну, родные) области.

6 голосов
/ 06 апреля 2010

Только потому, что в комментарии недостаточно места для этого. Думайте о попытке ... поймать как цикл if ... else. Вы не ожидаете следующего:

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

чтобы распечатать последнее условие ("\ $ a == 11"), потому что первое условие elseif уже выполнено То же самое и с попыткой ... поймать. Если условие выполнено, поиск новых условий в той же области не продолжается.

1 голос
/ 19 мая 2014

Я не уверен, допустимо ли следующее («попробовать» внутри блока catch), но дает ожидаемый результат:

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";
}

Дает вывод:

throwing AnotherException
caught AnotherException
throwing MyException
caught MyException
0 голосов
/ 29 мая 2013

Не уверен, считается ли это ответом или нет, но ответ даже проще, чем изложенный здесь.Для каждой попытки может быть запущен только ОДИН блок захвата, и он всегда будет самым конкретным применимым.

В этом случае исключение AnotherException выбрасывается и обрабатывается первым блоком захвата внутреннего try / catch, поэтомуэто не будет обработано вторым блоком catch.Новое исключение, выброшенное в блоке catch, обрабатывается внешним try / catch.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...