Blok Try / Catch w PHP nie przechwytuje wyjątku

98

Próbuję uruchomić ten przykład nr 1 z tej strony: http://php.net/manual/en/language.exceptions.php

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}
try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
// Continue execution
echo "Hello World\n";
?>

Jednak zamiast żądanego wyniku otrzymuję:

0.2
Fatal error: Uncaught exception 'Exception' with message 'Division by zero.' 
in xxx:
7 Stack trace: #0 xxx(14): inverse(0) #1 {main} thrown in xxx on line 7

Środowisko deweloper używam jest UniServer 3.5zPHP 5.2.3

Krassi
źródło
1
Czy możesz pokazać nam swój kod? Jedynym błędem, jaki możesz zrobić, aby uzyskać ten błąd, jest złapanie niewłaściwego wyjątku (lub żadnego).
Tammo
2
Kod jest DOKŁADNIE identyczny (właśnie dodałem kilka nowych linii) ... w każdym razie skopiowałem kod jeszcze raz do pliku testowego i tutaj jest ten sam komunikat o błędzie: 0.2 Błąd krytyczny: Nieprzechwycony wyjątek „Wyjątek” z komunikatem „Dzielenie przez zero ”. in W: \ www \ test.php: 4 Ślad stosu: # 0 W: \ www \ test.php (11): inverse (0) # 1 {main} wrzucono do W: \ www \ test.php w linii 4 Naprawdę nie mam pojęcia, co się tam dzieje ... może wadliwa konfiguracja PHP?
Krassi
1
Niektóre starsze wersje rozszerzeń powodowały problemy z obsługą wyjątków. Wersja 5.2.3 jest stara i może być przyczyną błędu. Czy możesz zaktualizować PHP? UniServer 3.5 jest również dość stary, biorąc pod uwagę, że obecna wersja produkcyjna to 5.5. Czy 3.5 to literówka?
wyjazd
1
Patrząc na informacje o wydaniu UniServer ( wiki.uniformserver.com/index.php/… ), 3.5 najwyraźniej nie jest literówką. Zaktualizuj do UniServer 5.5 i wypróbuj ponownie przykładowy kod.
wyjazd
1
outis, dzięki za cynk :). To właśnie zrobiłem wtedy - przerzuciłem się na XAMPP (nie podoba mi się nowa wersja UniServer). 3.5 nie jest literówką, ale serwer działał idealnie dla mnie, więc nigdy nie zawracałem sobie głowy aktualizacją.
Krassi

Odpowiedzi:

219

Właśnie miałem ten dokładny problem, w którym wydawało się, że nawet skopiowałem nazwę wyjątku, a jednak go nie złapałem. Okazało się, że to mój głupi błąd, ale pomyślałem, że powinienem tutaj zamieścić swoją sprawę na wypadek, gdyby był ktoś w takiej samej sytuacji.

Miałem wyjątek w moim nazw nazwie i skrypt był w przestrzeni nazw o nazwie B . Problem polegał na tym, że miałem A \ MyException, który jest równy (w PHP) \ B \ A \ MyException (ponieważ mój skrypt znajduje się w przestrzeni nazw o nazwie B !). Wszystko, co musiałem zrobić, aby to naprawić, to dodać ukośnik odwrotny (lub jak to się nazywa) do nazwy wyjątku, aby wyglądał tak: \ A \ MyException

Pijusn
źródło
7
bardzo dziękuję za opublikowanie tego, ponieważ spędziłbym kilka dni, nie zdając sobie sprawy z mojego błędu.
tipu
79
To rozwiązało mój problem, powinien być prosty leniwy blok catch w kodzie z przestrzenią nazw catch (\Exception $e). Bez odwrotnego ukośnika Exceptionjest specyficzna dla przestrzeni nazw i nie zostanie dopasowana (ani złapana).
joemaller
3
Dzięki za opublikowanie tego!
keepkimi
2
Dziękuję za opublikowanie tego, właśnie spędziłem kilka ostatnich godzin szalejąc nad tym, dlaczego mój blok catch nie działa. Major facepalm.
Mitch
4
Twoje zdrowie! Uratowałem mój dzień (i neurony ...) :)
warzywo
68

Dość stare pytanie, ale ...

Ja też miałem ten problem (i tak znalazłem ten post), ale prosty eksperyment pozwolił mi znaleźć rozwiązanie. Po prostu spróbuj zmienić Exceptionna \Exception. Pracował dla mnie!

EDYTOWAĆ:

Jak zauważył Sivann w komentarzach, użycie przestrzeni nazw powinno zrobić to samo. Więc po prostu umieść use \Exception as Exception;przed deklaracją klasy.

Enethion
źródło
Znakomity! :) Prawdopodobnie zajęłoby mi to godziny, po prostu nie myślałem o przestrzeni nazw. Dzięki!
Alexander Gilmanov
Tak! także: "użyj \ Wyjątek jako wyjątku;" na górze robi to samo.
sivann
@ sii-anik Spróbuj użyć przestrzeni nazw tak, jak napisał sivann.
Enethion
po prostu use Exception;powinienem to zrobić
Diego Ponciano
32

Spróbuj catch(\Exception $e)zamiast tego catch(Exception $e). Jeśli używasz kodu, o którym nie znasz zbyt dobrze, lub - szczególnie - jeśli używasz frameworka, może on zastąpić domyślny wyjątek PHP jednym z własnych, a zatem możesz przejść do złej ścieżki i uzyskać niepożądany wynik. Jeśli po prostu wstawisz \Exception, jesteś pewien, że przechwytujesz wyjątek podstawowy PHP.

Vladimir Despotovic
źródło
@crassi, czy wypróbowałeś moją sugestię?
Vladimir Despotovic
2
zrobiło to dla mnie
cljk
20

Nie możesz użyć typowych bloków try {} catch {} w PHP, tak jak możesz to zrobić w innym języku, takim jak C # (Csharp).

Jeśli to zrobisz:

try{
    //division by zero
    $number = 5/0;
}
catch(Exception $ex){
    echo 'Got it!';
}

Nie zobaczysz komunikatu „Rozumiem!” wiadomość nigdy. Czemu? Dzieje się tak dlatego, że PHP zawsze potrzebuje wyjątku, aby został „wyrzucony”. Musisz ustawić własny program obsługi błędów i zgłosić z nim wyjątek.

Zobacz funkcję set_error_handler : http://php.net/manual/es/function.set-error-handler.php

Rowinson Gallego
źródło
6
To nie to samo;) Musisz samemu rzucić wyjątek i to właśnie powiedziałem (<< To tylko dlatego, że PHP zawsze potrzebuje wyjątku, aby być „rzuconym” >>) @JaredFarrish
Rowinson Gallego
Tak, ale dlaczego to nie to samo?
Jared Farrish
Ten link jest martwy, ale uznałem to za przydatne: w3schools.com/php/func_error_set_error_handler.asp
Loathing
W PHP w wersji 7.3.9 $number = 5/0;nie zgłasza wyjątku. $numberjest ustawiony INF.
virtualmic
6

Moja inicjał jest jednak taki, że masz literówkę w nazwie wyjątku, który wychwytujesz / rzucasz, ale jeśli twój kod jest dokładnie taki sam, nie jestem pewien, co się dzieje.

Wypróbuj następującą modyfikację oryginalnego skryptu i wklej wyniki. Pomoże to nieco lepiej zdiagnozować problem.

<?php

//set up exception handler to report what we didn't catch
function exception_handler($exception) {

    if($exception instanceof MyException) {
        echo "you didn't catch a myexception instance\n";

    } else if($exception instanceof Exception) {
        echo "you didn't catch a exception instance\n";

    } else {
        echo "uncaught exception of type: ".gettype($exception)."\n";
    }

    echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

//install the handler
set_exception_handler('exception_handler');

class MyException extends Exception {
}

function inverse($x) {
    if (!$x) {
        throw new MyException('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (MyException $e) {
    echo 'Caught myexception: ',  $e->getMessage(), "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';
?>
francuski
źródło
4

Miałem ten sam problem z kolejnymi konfiguracjami,

PHP 5.2.14 (cli) (zbudowano: 12 sierpnia 2010 17:32:30) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies with eAccelerator v0.9.5. 1 , Copyright (c) 2004-2006 eAccelerator, by eAccelerator

Rozwiązaniem jest albo wyłączenie eAcceleratora, albo jego aktualizacja. Wypróbowałem oba i obie poprawki zadziałały. Błąd został zgłoszony tutaj https://eaccelerator.net/ticket/242 (uwaga: firefox narzeka na swój certyfikat SSL).

Teraz uruchamiam spróbuj złapać poprawnie z następującymi konfiguracjami,

PHP 5.2.4 (cli) (zbudowany: 16 października 2007 09:13:35) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies with eAccelerator v0.9.6. 1 , Copyright (c) 2004-2010 eAccelerator, by eAccelerator

Yawar
źródło
3

w Xdebug jest ustawienie:

xdebug.show_exception_trace = 1

Zmusi to php do wypisywania wyjątków nawet w bloku try catch. Włącz to0

user2950254
źródło
2
W moim przypadku musiałem całkowicie wyłączyć moduł xdebug (zmiana xdebug.show_exception_trace nie wystarczyła).
Thomas Sahlin
Dziękuję za to przypomnienie. Przez chwilę byłem całkowicie zdezorientowany.
Brian Litzinger
3

Jeśli używasz PHP 7, możesz potrzebować Throwable zamiast Exception

user5528384
źródło
To jest dość stary post. Zapoznaj się z datą tematu, zanim zdecydujesz się odpowiedzieć. Poza tym twoja odpowiedź nie jest zbyt pomocna, ponieważ jest:
niepełna
1
Wyjaśnienie jest takie, że PHP7 używa Throwable zamiast Exception. Ta dyskusja była pierwszą, jaką znalazłem, kiedy napotkałem problem i chciałem wnieść swój wkład. Takie komentarze to powody, dla których Stack nie jest przyjazny dla społeczności.
user5528384
1
nie miałem zamiaru cię urazić. Ten post pojawił się w kolejce Recenzji „Pierwsze posty” i moim zdaniem nie było przydatne umieszczanie odpowiedzi na dość stare pytanie. A w momencie pisania tego tekstu, Question Throwable nie został nawet wynaleziony w świecie PHP. Byłoby pomocne, gdybyś napisał w swojej odpowiedzi, że Throwable jest interfejsem zaimplementowanym przez wyjątek (i błąd), a zatem można go również złapać. Ale to nie jest uzupełnienie wyjątku.
monofoniczny
1

TLDR; upewnij się, że masz use Exception;na górze oba pliki php

Panie Heelis
źródło
0

Ja też tego doświadczam. Przeczytałem komentarz Rowinsona Gallego, który stwierdza, że ​​należy wyrzucić wyjątek. Więc zmodyfikowałem mój kod z:

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw $e;
}

w :

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw new Exception($e->getMessage(),$e->getCode());
}

To działa.

Fauzie Adriansyah
źródło