Перехват нескольких типов исключений в одном блоке перехвата
Я хотел бы более чистый способ получить следующую функциональность, чтобы поймать AError и BError в один блок:
try
{
/* something */
}
catch( AError, BError $e )
{
handler1( $e )
}
catch( Exception $e )
{
handler2( $e )
}
есть ли способ сделать это? Или мне придется ловить их отдельно?
AError и Berror есть общий базовый класс, но они также разделяют его с другими типами, которые я хотел бы пройти до handler2, так что я не могу просто поймать базовый класс.
11 ответов:
в последних версиях PHP это возможно. Смотрите ответ ниже.
если вы можете изменить исключениями, использовать этот ответ.
если вы не можете, вы можете попробовать поймать все с
Exceptionа затем проверить, какое исключение было брошено сinstanceof.try { /* something */ } catch( Exception $e ) { if ($e instanceof AError OR $e instanceof BError) { // It's either an A or B exception. } else { // Keep throwing it. throw $e; } }но наверное, было бы лучше используйте несколько блоков catch, как описано выше ответ.
try { /* something */ } catch( AError $e ) { handler1( $e ); } catch ( BError $b ) { handler2( $e ); }
обновление:
начиная с PHP 7.1, это доступно.
синтаксис:
try { // Some code... } catch(AError | BError $e) { // Handle exceptions } catch(Exception $e) { // Handle the general case }https://wiki.php.net/rfc/multiple-catch
https://github.com/php/php-src/commit/0aed2cc2a440e7be17552cc669d71fdd24d1204a
для PHP до 7.1:
несмотря на то, что эти другие ответы сказать, вы можете поймать
AErrorиBErrorв том же блоке (это несколько проще, если вы сами определяете исключения). Даже учитывая, что есть исключения, которые вы хотите "провалить", вы все равно должны иметь возможность определить иерархию в соответствии с вашими потребностями.abstract class MyExceptions extends Exception {} abstract class LetterError extends MyExceptions {} class AError extends LetterError {} class BError extends LetterError {}затем:
catch(LetterError $e){ //voodoo }Как видите,здесь и здесь, даже
SPLисключения по умолчанию имеют иерархию, которую вы можете использовать. Кроме того, как указано в руководство PHP:при возникновении исключения, кода после оператора не будет казнен, и PHP предпримет попытку найти первый блок catch, перехватывающий.
это означает, что вы также могли бы
class CError extends LetterError {}который вам нужно обрабатывать иначе, чем
AErrorилиBError, так что ваш catch заявление будет выглядеть так:catch(CError $e){ //voodoo } catch(LetterError $e){ //voodoo }если у вас был случай, когда было двадцать или более исключений, которые законно принадлежали к одному и тому же суперклассу, и вам нужно было обработайте пять (или любую большую группу) из них в одну сторону, а остальные-в другую, вы все равно можете это сделать.
interface Group1 {} class AError extends LetterError implements Group1 {} class BError extends LetterError implements Group1 {}и затем:
catch (Group1 $e) {}использование ООП, когда речь заходит об исключениях, очень мощно. Используя такие вещи, как
get_classилиinstanceofбездари, и его следует избегать, если это возможно.еще одно решение, которое я хотел бы добавить, - это поместить функциональность обработки исключений в свой собственный метод.
вы могли бы
function handleExceptionMethod1(Exception $e) { //voodoo } function handleExceptionMethod2(Exception $e) { //voodoo }предполагая, что вы абсолютно не можете контролировать иерархии классов исключений или интерфейсы (и там почти всегда будет be a way), вы можете сделать следующее:
try { stuff() } catch(ExceptionA $e) { $this->handleExceptionMethod1($e); } catch(ExceptionB $e) { $this->handleExceptionMethod1($e); } catch(ExceptionC $e) { $this->handleExceptionMethod1($e); } catch(Exception $e) { $this->handleExceptionMethod2($e); }таким образом, у вас все еще есть только одно местоположение кода, которое вы должны изменить, если ваш механизм обработки исключений должен измениться, и вы работаете в общих конструкциях ООП.
приедет в PHP 7.1 есть возможность поймать несколько типов.
Так что вот так:
<?php try { /* ... */ } catch (FirstException $ex) { $this->manageException($ex); } catch (SecondException $ex) { $this->manageException($ex); } ?>и
<?php try { } catch (FirstException | SecondException $ex) { $this->manageException($ex); } ?>функционально эквивалентны.
начиная с PHP 7.1,
catch( AError | BError $e ) { handler1( $e ) }интересно, что вы также можете:
catch( AError | BError $e ) { handler1( $e ) } catch (CError $e){ handler2($e); } catch(Exception $e){ handler3($e); }и в более ранних версиях PHP:
catch(Exception $ex){ if($ex instanceof AError){ //handle a AError } elseif($ex instanceof BError){ //handle a BError } else { throw $ex;//an unknown exception occured, throw it further } }
в этой статье рассматривается вопрос electrictoolbox.com/php-catch-multiple-exception-types. содержание поста скопировано непосредственно из статьи:
пример исключения
вот некоторые примеры исключений, которые были определены для целей этого примера:
class FooException extends Exception { public function __construct($message = null, $code = 0) { // do something } } class BarException extends Exception { public function __construct($message = null, $code = 0) { // do something } } class BazException extends Exception { public function __construct($message = null, $code = 0) { // do something } }обработка нескольких исключений
это очень просто - может быть блок catch для каждого типа исключения, который может быть бросил:
try { // some code that might trigger a Foo/Bar/Baz/Exception } catch(FooException $e) { // we caught a foo exception } catch(BarException $e) { // we caught a bar exception } catch(BazException $e) { // we caught a baz exception } catch(Exception $e) { // we caught a normal exception // or an exception that wasn't handled by any of the above }Если возникает исключение, которое не обрабатывается ни одним из других операторов catch, оно будет обрабатываться блоком catch(Exception $e). Это не обязательно должен быть последним.
в качестве расширения принятого ответа вы можете переключить тип исключения, что приведет к шаблону, который несколько похож на исходный пример:
try { // Try something } catch (Exception $e) { switch (get_class($e)) { case 'AError': case 'BError': // Handle A or B break; case 'CError': // Handle C break; case default: // Rethrow the Exception throw $e; } }
вот разумная альтернатива, если у вас нет контроля над определением исключений. Используйте имя переменной исключения, чтобы классифицировать исключения при их перехвате. Затем проверьте переменную исключения после блока try / catch.
$ABError = null; try { // something } catch (AError $ABError) { // let the exception fall through } catch (BError $ABError) { // let the exception fall through } catch (Exception $e) { handler2($e); } if ($ABError) { handler1($ABError); }этот несколько странный подход, вероятно, стоит того, если существует много дублирования между реализациями блока catch.
помимо провала, также можно перейти с помощью перейти. Это очень полезно, если вы хотите увидеть, как мир горит.
<?php class A_Error extends Exception {} class B_Error extends Exception {} class C_Error extends Exception {} try { throw new A_Error(); } catch (A_Error $e) { goto abc; } catch (B_Error $e) { goto abc; } catch (C_Error $e) { abc: var_dump(get_class($e)); echo "Gotta Catch 'Em All\n"; }
отличный способ использовать
set_exception_handler.предупреждение!!! с PHP 7 Вы можете получить белый экран смерти для фатальных ошибок. Например, если вы вызываете метод для не-объекта, вы обычно получаете
Fatal error: Call to a member function your_method() on nullи вы ожидали бы увидеть это, если сообщение об ошибке включено.вышеуказанная ошибка не будет поймана с
catch(Exception $e). Вышеприведенная ошибка не вызовет никакого пользовательского обработчика ошибок, установленногоset_error_handler.вы должны использовать
catch(Error $e){ }, чтобы поймать ошибки в PHP7. . Этот может помочь:class ErrorHandler{ public static function excep_handler($e) { print_r($e); } } set_exception_handler(array('ErrorHandler','excep_handler'));
ХМ, есть много решений, написанных для php версии ниже 7.1.
вот еще один простой для тех, кто не хочет ловить все исключения и не может сделать общие интерфейсы:
<?php $ex = NULL try { /* ... */ } catch (FirstException $ex) { // just do nothing here } catch (SecondException $ex) { // just do nothing here } if ($ex !== NULL) { // handle those exceptions here! } ?>
Comments