Le bloc Try / Catch en PHP n'attrape pas l'exception

98

J'essaye d'exécuter cet exemple # 1 à partir de cette page: 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";
?>

Cependant, au lieu de la sortie souhaitée, j'obtiens:

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'environnement de développement que j'utilise est UniServer 3.5avecPHP 5.2.3

Krassi
la source
1
Pouvez-vous nous montrer votre code? La seule erreur que vous pouvez faire pour obtenir cette erreur est de détecter la mauvaise exception (ou aucune).
Tammo
2
Le code est EXACTEMENT identique (je viens d'ajouter quelques nouvelles lignes) ... de toute façon, j'ai recopié le code une fois de plus dans un fichier de test et voici le même message d'erreur: 0.2 Erreur fatale: Exception non interceptée 'Exception' avec le message 'Division par zéro ». dans W: \ www \ test.php: 4 Trace de pile: # 0 W: \ www \ test.php (11): inverse (0) # 1 {main} lancé dans W: \ www \ test.php sur la ligne 4 Je n'ai vraiment aucune idée de ce qui se passe là-bas ... peut-être une configuration PHP défectueuse?
Krassi
1
Certaines anciennes versions d'extensions posaient des problèmes de gestion des exceptions. 5.2.3 est ancien et un bogue peut être à l'origine de l'erreur. Pouvez-vous mettre à jour PHP? UniServer 3.5 est également assez ancien, étant donné que la version de production actuelle est la 5.5. 3.5 est-il une faute de frappe?
sortie le
1
En regardant les informations de version d'UniServer ( wiki.uniformserver.com/index.php/… ), 3.5 n'est apparemment pas une faute de frappe. Mettez à niveau vers UniServer 5.5 et réessayez l'exemple de code.
sortie le
1
outis, merci pour le tuyau :). C'est ce que j'ai fait à l'époque - je suis passé à XAMPP (je n'aime pas la nouvelle version d'UniServer). 3.5 n'est pas une faute de frappe, mais le serveur a parfaitement fonctionné pour moi, donc je n'ai jamais pris la peine de le mettre à niveau.
Krassi

Réponses:

219

J'ai juste eu ce problème exact où il semblait que j'avais même copié le nom de l'exception et pourtant il ne l'a pas attrapé. Il s'est avéré que c'était ma stupide erreur, mais j'ai pensé que je devrais publier mon cas ici au cas où quelqu'un d'autre serait dans la même situation.

J'ai eu mon exception dans mon espace de noms appelé A et le script était dans un espace de noms appelé B . Le problème était que j'avais A \ MyException qui équivaut (en PHP) \ B \ A \ MyException (car mon script est dans l'espace de noms appelé B !). Tout ce que j'avais à faire pour résoudre ce problème était d'ajouter une barre oblique inverse (ou son nom) au nom de l'exception afin que cela ressemble à ceci: \ A \ MyException

Pijusn
la source
7
merci beaucoup d'avoir posté ceci car j'aurais passé plusieurs jours sans me rendre compte de mon erreur.
tipu
79
Cela a résolu mon problème, un simple bloc catch paresseux dans le code à espace de noms devrait être catch (\Exception $e). Sans la barre oblique inverse Exceptionest spécifique à l'espace de noms et ne sera pas mis en correspondance (ni intercepté).
joemaller
3
Merci d'avoir publié ceci!
keepkimi
2
Merci d'avoir posté ceci, je viens de passer les dernières heures à me demander pourquoi mon bloc catch ne fonctionnait pas. Facepalm majeur.
Mitch
4
À votre santé! A sauvé ma journée (et les neurones ...) :)
légume
68

Question assez ancienne, pourtant ...

J'ai eu ce problème aussi (et c'est comme ça que j'ai trouvé ce post) mais une simple expérience m'a permis de trouver la solution. Essayez simplement de passer Exceptionà \Exception. A travaillé pour moi!

ÉDITER:

Comme sivann l'a souligné dans les commentaires, l'utilisation de l'espace de noms devrait faire la même chose. Alors mettez simplement use \Exception as Exception;avant votre déclaration de classe.

Enethion
la source
Brillant! :) Cela me prendrait probablement des heures à comprendre, je ne pensais tout simplement pas à l'espacement des noms. Merci!
Alexander Gilmanov
Oui! aussi: "use \ Exception as Exception;" au sommet fait la même chose.
sivann
@ sii-anik Essayez d'utiliser l'espace de noms comme l'a écrit sivann.
Enethion
juste use Exception;devrait le faire
Diego Ponciano
32

Essayez de mettre catch(\Exception $e)au lieu de catch(Exception $e). Si vous utilisez un code que vous ne connaissez pas très bien, ou - en particulier - si vous utilisez un framework, il peut remplacer l'exception PHP par défaut par l'une des siens, et par conséquent, vous risquez d'aller sur le mauvais chemin et d'obtenir le résultat indésirable. Si vous venez de mettre \Exception, vous êtes sûr que vous attrapez l'exception PHP de base.

Vladimir Despotovic
la source
@crassi, avez-vous essayé ma suggestion?
Vladimir Despotovic
2
qui l'a fait pour moi
cljk
20

Vous ne pouvez pas utiliser les blocs try {} catch {} typiques en PHP comme vous pourriez le faire dans un autre langage comme C # (Csharp).

Si tu fais ça:

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

Vous ne verrez pas le "Got it!" message jamais. Pourquoi? C'est juste parce que PHP a toujours besoin d'une exception pour être «levée». Vous devez définir votre propre gestionnaire d'erreurs et lancer une exception avec lui.

Voir la fonction set_error_handler : http://php.net/manual/es/function.set-error-handler.php

Rowinson Gallego
la source
6
Ce n'est pas la même chose;) Vous aviez besoin de lever une exception par vous-même, et c'est ce que j'ai dit (<< C'est juste parce que PHP a toujours besoin d'une exception pour être "Thrown" >>) @JaredFarrish
Rowinson Gallego
Oui, mais en quoi n'est-ce pas pareil?
Jared Farrish
Ce lien est mort, mais j'ai trouvé cela utile: w3schools.com/php/func_error_set_error_handler.asp
Loathing
Dans la version 7.3.9 de PHP, $number = 5/0;ne lève pas d'exception. $numberest défini pour être INF.
virtualmic
6

Ma première remarque est que vous avez une faute de frappe dans le nom de l'exception que vous attrapez / lancez, mais si votre code est exactement le même, je ne sais pas exactement ce qui se passe.

Essayez la modification suivante du script d'origine et collez vos résultats. Cela vous aidera à diagnostiquer un peu mieux votre problème.

<?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';
?>
francais
la source
4

J'ai eu le même problème avec les configurations suivantes,

PHP 5.2.14 (cli) (build: 12 août 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, par eAccelerator

La solution consiste à désactiver eAccelerator ou à le mettre à jour. J'ai essayé les deux et les deux correctifs ont fonctionné. Le bug est signalé ici https://eaccelerator.net/ticket/242 (NB. Firefox se plaint de son certificat SSL).

Maintenant, je cours, essayez d'attraper correctement avec les configurations suivantes,

PHP 5.2.4 (cli) (construit: 16 octobre 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, par eAccelerator

Yawar
la source
3

dans Xdebug il y a un paramètre:

xdebug.show_exception_trace = 1

Cela forcera php à afficher des exceptions même dans un bloc try catch. Transformez ceci en0

user2950254
la source
2
Dans mon cas, j'ai dû désactiver complètement le module xdebug (changer xdebug.show_exception_trace n'était pas suffisant).
Thomas Sahlin
Merci pour ce rappel. J'étais complètement confus pendant un certain temps.
Brian Litzinger
3

Si vous utilisez PHP 7, vous aurez peut-être besoin de Throwable au lieu d'Exception

user5528384
la source
C'est un article assez ancien. Jetez un œil à la date du sujet avant de décider de répondre. À côté de cela, votre réponse n'est pas vraiment utile car elle est: - pas complète - pas d'explication pourquoi
monofone
1
L'explication est que PHP7 utilise Throwable au lieu d'Exception. Cette discussion a été la première que j'ai trouvée lorsque j'ai rencontré le problème et j'ai voulu y contribuer. Des commentaires comme ceux-ci sont les raisons pour lesquelles Stack n'est pas convivial pour la communauté.
user5528384
1
ce n'était pas mon intention de vous offenser. Ce message est apparu dans la file d'attente "Premiers messages" et à mon avis, il n'était pas utile de publier une réponse sur une question assez ancienne. Et au moment de la rédaction de cet article, la Question Throwable n'a même pas été inventée dans le monde PHP. Il serait utile que vous écriviez dans votre réponse que Throwable est l'interface implémentée par Exception (et Error) et peut donc également être interceptée. Mais ce n'est pas un complément à une exception.
monofone
1

TLDR; assurez-vous que vous avez use Exception;en haut des deux fichiers php

Monsieur Heelis
la source
0

Je vis cela aussi. J'ai lu le commentaire de Rowinson Gallego sur l'état d'exception qui doit être levé. J'ai donc modifié mon code à partir de:

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

dans:

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

Ça marche.

Fauzie Adriansyah
la source