Aktualizacja:
Od PHP 7.1 jest to dostępne.
Składnia jest następująca:
try
{
// Some code...
}
catch(AError | BError $e)
{
// Handle exceptions
}
catch(Exception $e)
{
// Handle the general case
}
Dokumenty: https://www.php.net/manual/en/language.exceptions.php#example-287
RFC: https://wiki.php.net/rfc/multiple-catch
Zatwierdź: https://github.com/php/php-src/commit/0aed2cc2a440e7be17552cc669d71fdd24d1204a
Dla PHP przed 7.1:
Pomimo tego, co mówią te inne odpowiedzi, możesz złapać AError
i BError
w tym samym bloku (jest to nieco łatwiejsze, jeśli to Ty definiujesz wyjątki). Nawet biorąc pod uwagę, że istnieją wyjątki, przez które chcesz „upaść”, nadal powinieneś być w stanie zdefiniować hierarchię odpowiadającą twoim potrzebom.
abstract class MyExceptions extends Exception {}
abstract class LetterError extends MyExceptions {}
class AError extends LetterError {}
class BError extends LetterError {}
Następnie:
catch(LetterError $e){
//voodoo
}
Jak widać tu i tutaj , nawet SPL
domyślne wyjątki mają hierarchię, którą można wykorzystać. Dodatkowo, jak stwierdzono w podręczniku PHP :
Po zgłoszeniu wyjątku kod następujący po instrukcji nie zostanie wykonany, a PHP spróbuje znaleźć pierwszy pasujący blok catch.
Oznacza to, że Ty też możesz mieć
class CError extends LetterError {}
które musisz obsługiwać inaczej niż AError
lub BError
, więc instrukcja catch wyglądałaby następująco:
catch(CError $e){
//voodoo
}
catch(LetterError $e){
//voodoo
}
Jeśli miałeś przypadek, w którym istniało dwadzieścia lub więcej wyjątków, które legalnie należały do tej samej nadklasy, i musiałeś poradzić sobie z pięcioma (lub jakąkolwiek dużą grupą) z nich w jedną stronę, a reszta w drugiej, nadal możesz to zrobić.
interface Group1 {}
class AError extends LetterError implements Group1 {}
class BError extends LetterError implements Group1 {}
I wtedy:
catch (Group1 $e) {}
Używanie OOP w przypadku wyjątków jest bardzo skuteczne. Używanie rzeczy takich jak hack get_class
lub instanceof
są hackami i należy ich unikać, jeśli to możliwe.
Innym rozwiązaniem, które chciałbym dodać, jest umieszczenie funkcji obsługi wyjątków we własnej metodzie.
Mógłbyś
function handleExceptionMethod1(Exception $e)
{
//voodoo
}
function handleExceptionMethod2(Exception $e)
{
//voodoo
}
Zakładając, że absolutnie nie ma możliwości kontrolowania hierarchii klas interfejsów lub interfejsów wyjątków (i prawie zawsze będzie sposób), możesz wykonać następujące czynności:
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);
}
W ten sposób nadal masz tylko jedną lokalizację kodu, którą musisz zmodyfikować, jeśli twój mechanizm obsługi wyjątków wymaga zmiany, i pracujesz w ogólnych konstrukcjach OOP.