Chciałbym czystszego sposobu na uzyskanie następujących funkcji, aby złapać AError
i BError
w jednym bloku:
try
{
/* something */
}
catch( AError, BError $e )
{
handler1( $e )
}
catch( Exception $e )
{
handler2( $e )
}
Czy jest na to sposób? Czy też muszę je łapać osobno?
AError
i Berror
mają wspólną klasę podstawową, ale dzielą ją także z innymi typami, do których chciałbym się zaliczyć handler2
, więc nie mogę po prostu złapać klasy podstawowej.
php
exception-handling
Dominic Gurto
źródło
źródło
Odpowiedzi:
Aktualizacja:
Od PHP 7.1 jest to dostępne.
Składnia jest następująca:
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
iBError
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.Następnie:
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 :Oznacza to, że Ty też możesz mieć
które musisz obsługiwać inaczej niż
AError
lubBError
, więc instrukcja catch wyglądałaby następująco: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ć.
I wtedy:
Używanie OOP w przypadku wyjątków jest bardzo skuteczne. Używanie rzeczy takich jak hack
get_class
lubinstanceof
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ś
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:
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.
źródło
AError
może być zaimplementowany w bibliotece / pliku, który jest aktualizowany przez stronę trzecią.W PHP> = 7.1 jest to możliwe. Zobacz odpowiedź poniżej.
Jeśli możesz zmodyfikować wyjątki, skorzystaj z tej odpowiedzi .
Jeśli nie możesz, możesz spróbować złapać wszystko,
Exception
a następnie sprawdzić, który wyjątek został zgłoszonyinstanceof
.Ale prawdopodobnie lepiej byłoby użyć wielu bloków catch, jak opisano we wspomnianej odpowiedzi .
źródło
finally
wypowiedzi. ;)... } else { throw($e); }
jeśli nie pasuje do dwóch. Przepraszam za być może złą składnię, przez jakiś czas nie widziałem php.W PHP 7.1 można łapać wiele typów.
Aby to:
i
są funkcjonalnie równoważne.
źródło
Od PHP 7.1
co ciekawe, możesz także:
oraz we wcześniejszych wersjach PHP:
źródło
Ten artykuł obejmuje pytanie electrictoolbox.com/php-catch-multiple-exception-types . Treść postu skopiowana bezpośrednio z artykułu:
Przykładowe wyjątki
Oto kilka przykładowych wyjątków, które zostały zdefiniowane na potrzeby tego przykładu:
Obsługa wielu wyjątków
To bardzo proste - dla każdego typu wyjątku, który może zostać zgłoszony, może istnieć blok przechwytujący:
Jeśli zgłoszony zostanie wyjątek, który nie jest obsługiwany przez żadną inną instrukcję catch, zostanie on obsłużony przez blok catch (wyjątek $ e). To niekoniecznie musi być ostatni.
źródło
catch (Throwable $e)
wychwycić wszystkie wyjątki. Zobacz także: php.net/manual/en/class.throwable.phpJako rozszerzenie zaakceptowanej odpowiedzi można zmienić typ wyjątku, co spowoduje, że wzorzec będzie podobny do oryginalnego przykładu:
źródło
Oto rozsądna alternatywa, jeśli nie masz kontroli nad definiowaniem wyjątków. Użyj nazwy zmiennej wyjątku, aby kategoryzować wyjątki, gdy zostaną złapane. Następnie sprawdź zmienną wyjątku po bloku try / catch.
To nieco dziwnie wyglądające podejście jest prawdopodobnie warte zachodu tylko wtedy, gdy istnieje wiele duplikacji między implementacjami bloku catch.
źródło
Oprócz upadku można również przejść na drugą stronę, używając goto . Jest to bardzo przydatne, jeśli chcesz zobaczyć, jak płonie świat.
3v4l.org
źródło
Świetnym sposobem jest użycie
set_exception_handler
.Ostrzeżenie!!! z PHP 7 możesz dostać biały ekran śmierci za fatalne błędy. Na przykład, jeśli wywołasz metodę na obiekcie niebędącym obiektem, normalnie byś ją otrzymał
Fatal error: Call to a member function your_method() on null
i spodziewałbyś się tego, jeśli raportowanie błędów jest włączone.Powyższy błąd NIE zostanie złapany
catch(Exception $e)
. Powyższy błąd NIE wyzwoli żadnej niestandardowej procedury obsługi błędów ustawionej przezset_error_handler
.Musisz użyć,
catch(Error $e){ }
aby wyłapać błędy w PHP7. . To może pomóc:źródło
catch (Throwable $e) { ... }
i gotowe. Zobacz także: php.net/manual/en/class.throwable.phpInną niewymienioną tutaj opcją jest użycie
code
atrybutu wyjątku, abyś mógł zrobić coś takiego:źródło
extends \Exception
?Hmm, istnieje wiele rozwiązań napisanych dla wersji php niższej niż 7.1.
Oto inny prosty dla tych, którzy nie chcą wychwytywać wszystkich wyjątków i nie mogą tworzyć wspólnych interfejsów:
źródło