Blocco Try / Catch in PHP che non cattura l'eccezione


97

Sto cercando di eseguire questo esempio n. 1 da questa pagina: 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";
?>

Tuttavia invece dell'output desiderato ottengo:

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

L'ambiente di sviluppo che sto usando è UniServer 3.5conPHP 5.2.3


1
Puoi mostrarci il tuo codice? L'unico errore che puoi fare per ottenere questo errore è rilevare l'eccezione sbagliata (o nessuna).
Tammo

2
Il codice è ESATTAMENTE identico (ho appena aggiunto alcune nuove righe) ... comunque, ho copiato il codice ancora una volta in un file di prova ed ecco lo stesso messaggio di errore: 0.2 Errore irreversibile: eccezione non rilevata 'Eccezione' con messaggio 'Divisione per zero . " in W: \ www \ test.php: 4 Stack trace: # 0 W: \ www \ test.php (11): inverse (0) # 1 {main} lanciato in W: \ www \ test.php sulla riga 4 Non ho davvero idea di cosa stia succedendo lì ... forse configurazione PHP difettosa?
Krassi

1
Alcune versioni di estensione precedenti hanno causato problemi con la gestione delle eccezioni. 5.2.3 è vecchio e potrebbe esserci un bug dietro l'errore. Puoi aggiornare PHP? Anche UniServer 3.5 è piuttosto vecchio, considerando che l'attuale versione di produzione è la 5.5. 3.5 è un errore di battitura?
uscita il

1
Guardando le informazioni sulla versione di UniServer ( wiki.uniformserver.com/index.php/… ), 3.5 apparentemente non è un errore di battitura. Aggiorna a UniServer 5.5 e prova di nuovo il codice di esempio.
uscita il

1
outis, grazie per il suggerimento :). Questo è quello che ho fatto allora: sono passato a XAMPP (non mi piace la nuova versione di UniServer). 3.5 non è un errore di battitura, ma il server ha funzionato perfettamente per me, quindi non mi sono mai preoccupato di aggiornarlo.
Krassi

Risposte:


217

Ho appena avuto questo problema esatto in cui sembrava che avessi persino copiato il nome dell'eccezione e tuttavia non l'ha rilevato. Si è scoperto che è stato un mio stupido errore, ma ho pensato di pubblicare il mio caso qui nel caso ci fosse qualcun altro nella stessa situazione.

Ho avuto la mia eccezione nel mio namespace chiamato A e lo script è stato in un namespace chiamato B . Il problema era che avevo A \ MyException che equivale a (in PHP) \ B \ A \ MyException (perché il mio script è nello spazio dei nomi chiamato B !). Tutto quello che dovevo fare per risolverlo era aggiungere una barra rovesciata (o come si chiama) al nome dell'eccezione in modo che fosse simile a questo: \ A \ MyException


7
grazie mille per aver postato questo perché sarei passato diversi giorni senza rendermi conto del mio errore.
tipu

79
Questo ha risolto il mio problema, dovrebbe essere un semplice blocco di cattura pigro nel codice con spazio dei nomi catch (\Exception $e). Senza la barra rovesciata Exceptionè specifico per lo spazio dei nomi e non verrà trovato (o catturato).
joemaller

3
Grazie per aver postato questo!
keepkimi

2
Grazie per aver postato questo, ho appena passato le ultime ore a impazzire per il motivo per cui il mio blocco di cattura non funzionava. Maggiore facepalm.
Mitch

4
Saluti! Mi ha salvato la giornata (e i neuroni ...) :)
verdura

67

Domanda piuttosto vecchia, eppure ...

Ho avuto anche questo problema (ed è così che ho trovato questo post) ma solo un semplice esperimento mi ha permesso di trovare la soluzione. Prova a cambiare Exceptionin \Exception. Ha funzionato per me!

MODIFICARE:

Come ha sottolineato sivann nei commenti, l'uso dello spazio dei nomi dovrebbe fare la stessa cosa. Quindi mettilo semplicemente use \Exception as Exception;prima della dichiarazione di classe.


Brillante! :) Probabilmente mi ci vorrebbero ore per capirlo, ma non pensavo allo spazio dei nomi. Grazie!
Alexander Gilmanov

Sì! anche: "usa \ Eccezione come eccezione;" in alto fa la stessa cosa.
sivann

@ sii-anik Prova a usare lo spazio dei nomi proprio come ha scritto sivann.
Enethion

basta use Exception;dovrebbe farlo
Diego Ponciano

Grazie! @Enethion
Noamway

32

Prova a mettere catch(\Exception $e)invece di catch(Exception $e). Se stai usando un codice che non conosci molto bene, o - soprattutto - se stai usando un framework, potrebbe sovrascrivere l'eccezione PHP predefinita con una delle sue, e quindi potresti andare sul percorso sbagliato e ottenere il risultato indesiderato. Se lo metti \Exception, sei sicuro di catturare l'eccezione PHP di base.


@crassi, hai provato il mio suggerimento?
Vladimir Despotovic

2
che ha fatto per me
cljk

20

Non puoi usare i tipici blocchi try {} catch {} in PHP come potresti fare in un altro linguaggio come C # (Csharp).

Se lo fai:

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

Non vedrai il messaggio "Capito!" messaggio mai. Perché? È solo perché PHP ha sempre bisogno di un'eccezione per essere "lanciata". È necessario impostare il proprio gestore degli errori e generare un'eccezione con esso.

Vedi la funzione set_error_handler : http://php.net/manual/es/function.set-error-handler.php


6
Non è la stessa cosa;) Dovevi lanciare un'eccezione da solo, ed era quello che ho detto (<< È solo perché PHP ha sempre bisogno di un'eccezione per essere "lanciato" >>) @JaredFarrish
Rowinson Gallego

Sì, ma come non è lo stesso?
Jared Farrish

Quel link è morto, ma l'ho trovato utile: w3schools.com/php/func_error_set_error_handler.asp
Loathing

Nella versione 7.3.9 di PHP, $number = 5/0;non solleva un'eccezione. $numberè impostato per essere INF.
virtualmic

6

Il mio iniziale però è che hai un errore di battitura nel nome dell'eccezione che stai catturando / lanciando, ma se il tuo codice è esattamente lo stesso non sono sicuro di cosa stia succedendo.

Prova la seguente modifica dello script originale e incolla i risultati. Aiuterà a diagnosticare un po 'meglio il tuo problema.

<?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';
?>

4

Ho avuto lo stesso problema con le seguenti configurazioni,

PHP 5.2.14 (cli) (costruito: 12 agosto 2010 17:32:30) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies con eAccelerator v0.9.5. 1 , Copyright (c) 2004-2006 eAccelerator, di eAccelerator

La soluzione è disabilitare eAccelerator o aggiornarlo. Ho provato entrambi ed entrambe le soluzioni hanno funzionato. Il bug è segnalato qui https://eaccelerator.net/ticket/242 (NB. Firefox si lamenta del proprio certificato SSL).

Ora sto eseguendo, prova a catturare correttamente con le seguenti configurazioni,

PHP 5.2.4 (cli) (costruito: 16 ottobre 2007 09:13:35) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies con eAccelerator v0.9.6. 1 , Copyright (c) 2004-2010 eAccelerator, di eAccelerator



3

in Xdebug c'è un'impostazione:

xdebug.show_exception_trace = 1

Questo costringerà php a produrre eccezioni anche in un blocco try catch. Trasforma questo in0


2
Nel mio caso ho dovuto disabilitare completamente il modulo xdebug (cambiare xdebug.show_exception_trace non era sufficiente).
Thomas Sahlin

Grazie per questo promemoria. Sono stato completamente confuso per un po '.
Brian Litzinger

3

Se stai usando PHP 7, potresti aver bisogno di Throwable invece di Exception


Questo è un post piuttosto vecchio. Dai un'occhiata alla data dell'argomento prima di decidere di rispondere. A parte questo, la tua risposta non è molto utile in quanto è: - non completa - nessuna spiegazione perché
monofone

1
La spiegazione è che PHP7 utilizza Throwable invece di Exception. Questa discussione è stata la prima che ho trovato quando ho riscontrato il problema e ho voluto contribuire. Commenti come questi sono motivi per cui Stack non è adatto alla comunità.
user5528384

1
non era mia intenzione offenderti. Questo post è apparso nella coda delle revisioni "Primi post" ea mio parere non è stato utile inserire una risposta su una domanda piuttosto vecchia. E al momento della stesura di questo articolo, il Question Throwable non è stato nemmeno inventato nel mondo PHP. Sarebbe utile se scrivessi nella tua risposta che Throwable è l'interfaccia implementata da Exception (ed Error) e quindi può essere catturata anche. Ma non è un supplemento a un'eccezione.
monofone



0

Anch'io sto vivendo questo. Ho letto il commento di Rowinson Gallego in cui si deve lanciare un'eccezione di stato. Quindi ho modificato il mio codice da:

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

in:

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

Funziona.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.