Оновлення:
Станом на PHP 7.1, це доступно.
Синтаксис:
try
{
// Some code...
}
catch(AError | BError $e)
{
// Handle exceptions
}
catch(Exception $e)
{
// Handle the general case
}
Документи: https://www.php.net/manual/en/language.exceptions.php#example-287
RFC: 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 спробує знайти перший відповідний блок лову.
Це означає, що ви могли також мати
class CError extends LetterError {}
з якою вам потрібно поводитися інакше, ніж AError
або BError
, щоб ваша заява на вилов виглядала б так:
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) {}
Використання OOP, коли мова йде про винятки, дуже потужне. Використовуючи речі , як get_class
і instanceof
є хакі, і його слід уникати , якщо це можливо.
Ще одне рішення, яке я хотів би додати, - це введення функціоналу обробки винятків у свій метод.
Можна було
function handleExceptionMethod1(Exception $e)
{
//voodoo
}
function handleExceptionMethod2(Exception $e)
{
//voodoo
}
Якщо припустити, що ви абсолютно не можете контролювати ієрархії класів винятків або інтерфейси (і майже завжди буде спосіб), ви можете зробити наступне:
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);
}
Таким чином, у вас все ще є єдине місце розташування коду, яке ви повинні змінити, якщо ваш механізм обробки винятків потребує змін, і ви працюєте в загальних конструкціях OOP.