49 votes

Existe-t-il un moyen d'attraper une exception sans avoir à créer une variable ?

En PHP, j'attrape parfois des exceptions avec try/catch :

try {
    ...
} catch (Exception $e) {
    // Nothing, this is normal
}

Avec ce genre de code, je me retrouve avec la variable $e qui est créé pour rien (beaucoup de ressources), et PHP_MD (PHP Mess Detector) crée un avertissement à cause d'une variable inutilisée.

3 votes

Une exception ne doit pas être traitée comme "normale" - c'est une exception ou pas. Qu'est-ce qui déclenche les exceptions ?

0 votes

Je vérifie que le modèle lève une exception quand il le devrait. J'ai donc un bloc catch vide car je veux juste tester que l'exception a été levée.

24voto

yivi Points 3635

À partir de PHP 8, il est possible d'utiliser une capture sans capture.

Voici le RFC correspondant qui a été voté favorablement à 48 contre 1.

Maintenant, il sera possible de faire quelque chose comme ça :

try {
    readFile($file);
} catch (FileDoesNotExist) {
    echo "File does not exist";
} catch (UnauthorizedAccess) {
    echo "User does not have the appropriate permissions to access the file";
    log("User attempted to access $file");
}

Ainsi, pour certains cas limites où les détails de l'exception ne sont pas pertinents et où le type d'exception fournit déjà tout le contexte nécessaire, il sera possible d'attraper l'exception sans créer une nouvelle variable.

0 votes

Pourriez-vous fournir une documentation pédagogique sur la façon dont cela fonctionne sans une Throw ? Je vérifie mes spots habituels, mais ils sont tous faits pour <8.0

19voto

TarranJones Points 159

Vous pouvez le faire avec PHP 8 @voir

PHP 5,7

Non, mais vous pouvez le désactiver.

try {
    ...
} catch (Exception $e) {
    // Nothing, this is normal
    unset($e);
}

Si c'est PHPMD qui cause ce problème, vous pouvez supprimer l'avertissement.

PHPMD supprimer les avertissements

class Bar {
    /**
     * This will suppress UnusedLocalVariable
     * warnings in this method
     *
     * @SuppressWarnings(PHPMD.UnusedLocalVariable)
     */
    public function foo() {

        try {
            ...
        } catch (Exception $e) {
            // Nothing, this is normal
            unset($e);
        }
    }
}

Je suppose que vous attrapez l'exception uniquement parce que vous devez le faire et non parce que vous le voulez. Avec PHP 5,7, vous devez utiliser un objet catch si vous voulez utiliser try et si vous utilisez un catch vous devez déclarer une variable.

8voto

Marc B Points 195501

C'est tout l'intérêt des exceptions - vous pouvez avoir plusieurs blocs catch différents pour attraper toutes les exceptions que vous voulez gérer. Les données de l'exception doivent être affectées quelque part, d'où la variable. Vous pourriez simplement faire quelque chose comme unset($e) à l'intérieur du bloc catch si vous ne voulez vraiment pas voir ces avertissements... ou désactivez les avertissements (généralement une mauvaise idée).

8voto

Wouter Florijn Points 853

Je suis fondamentalement en désaccord avec les réponses de Marc B et d'Artefacto. Il y a des cas où omettre le catch est préférable ou même la seule option. En particulier lors de l'utilisation de bibliothèques externes (où vous n'avez aucun contrôle sur les exceptions qui sont lancées) et/ou d'opérations asynchrones.

Par exemple :

Je veux créer un fichier uniquement s'il n'existe pas encore. J'utilise une bibliothèque d'E/S externe. Imaginez qu'elle ait File::exists($fileName) y File::create($fileName) méthodes.

Option 1 (si l'omission de la prise était possible) :

try {
    File::create($fileName);
}
// Go on with the rest of the code.

Option 2 (sans try/catch) :

if (!File::exists($fileName))
    File::create($fileName);

Ici, l'option 1 est parfaitement valable, car l'option 2 présente deux problèmes importants :

  1. Si plusieurs threads sont en cours d'exécution et parcourent cette section de code en même temps, il se peut que le thread A vérifie d'abord si le fichier existe. Ensuite, le thread B vérifie si le fichier existe. Ils constatent tous deux qu'il n'existe pas. Le thread A crée le fichier. Le thread B tente alors de le créer à nouveau et lève une exception, bien que vous utilisiez la vérification if.
  2. Il est très probable que la bibliothèque elle-même effectue déjà les tâches suivantes !File::exists($fileName) vérifier. Vous gaspillez donc un appel qui est déjà fait.

Notez que si File::create lance d'autres exceptions qui pourraient être inattendues, il serait bon de les attraper.

Conclusion

Affirmer que quelque chose est jamais une bonne idée, est presque jamais une bonne idée. Il y a toujours des exceptions (hehe) à la règle. Comme toute convention ou modèle de conception, il s'agit simplement d'une règle empirique destinée à aider les développeurs moins expérimentés à prendre la bonne décision.

0 votes

Vous devriez au moins enregistrer que l'exception s'est produite. Ne rien faire dans les blocs catch crée des "trous noirs" dans votre code - quelque chose ne fonctionne pas et vous ne savez pas pourquoi - et il n'y a aucun moyen pour vous de le tracer autrement qu'en exécutant le débogueur ligne par ligne jusqu'à ce que le problème survienne.

2 votes

@superrafal ce n'est pas du tout le cas dans mon exemple. Je sais exactement quelle exception est levée, et je veux l'ignorer et passer à autre chose. Pourquoi aurais-je besoin d'enregistrer chaque fois que quelque chose d'inoffensif et de prévisible se produit ?

7voto

Artefacto Points 50896

Non.

Dans tous les cas, c'est généralement une mauvaise idée d'attraper une exception et de ne rien faire ; les exceptions existent précisément pour vous obliger à gérer la circonstance exceptionnelle (sinon l'exécution est interrompue), il est donc compréhensible que le langage ne facilite pas un tel cas d'utilisation.

5 votes

En même temps, c'est généralement une mauvaise idée de lancer une exception quand on a probablement juste besoin d'un code d'état. Si les exceptions étaient réellement exceptionnelles, nous ne verrions pas autant de blocs try/catch inutiles. En particulier, de nombreux utilitaires de réseau lèvent des exceptions dès qu'il y a un problème de réseau, ce qui brise l'encapsulation et n'aide pas vraiment le programmeur. Un problème de réseau ne devrait pas être exceptionnel lorsque vous êtes un utilitaire de réseau, vous devriez être en mesure de le gérer en interne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X