420 votes

Puis-je try/catch un avertissement?

J'ai besoin d'attraper quelques mises en garde d'être levée à partir de certaines fonctions natives de php, puis de les traiter.

Plus précisément:

array dns_get_record  ( string $hostname  [, int $type= DNS_ANY  [, array &$authns  [, array &$addtl  ]]] )

Il lance un avertissement lorsque la requête DNS échoue.

try/catch ne fonctionne pas parce qu'un avertissement n'est pas une exception.

J'ai maintenant 2 options:

  1. set_error_handler semble exagéré, parce que je dois l'utiliser pour filtrer chaque avertissement dans la page (est-ce vrai?);

  2. Ajuster le rapport d'erreur/d'affichage de sorte que ces avertissements ne pas obtenir un écho à l'écran, puis vérifier la valeur de retour; si c'est false, aucun enregistrement n'est trouvé pour le nom d'hôte.

Quelle est la meilleure pratique ici?

426voto

Philippe Gerber Points 6360

Définir et restaurer gestionnaire d'erreur

Une possibilité est de définir votre propre gestionnaire d'erreur avant l'appel et de rétablir le précédent gestionnaire d'erreur plus tard avec restore_error_handler().

set_error_handler(function() { /* ignore errors */ });
dns_get_record();
restore_error_handler();

Vous pouvez construire sur cette idée, et écrire une ré-utilisable gestionnaire d'erreur, qui enregistre les erreurs pour vous.

set_error_handler([$logger, 'onSilencedError']);
dns_get_record();
restore_error_handler();

Tournant les erreurs dans les exceptions

Vous pouvez utiliser set_error_handler() et de la ErrorException classe de tourner toutes les erreurs php dans les exceptions.

set_error_handler(function handleError($errno, $errstr, $errfile, $errline, array $errcontext) {
    // error was suppressed with the @-operator
    if (0 === error_reporting()) {
        return false;
    }

    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

try {
    dns_get_record();
} catch (ErrorException $e) {
    // ...
}

La chose importante à noter lors de l'utilisation de votre propre gestionnaire d'erreur est qu'il ignore l' error_reporting réglage et passer toutes les erreurs (les avertissements, mises en garde, etc.) à votre gestionnaire d'erreur. Vous pouvez définir un deuxième argument en faveur de set_error_handler() pour définir les types d'erreur que vous souhaitez recevoir, ou d'accéder au réglage du courant à l'aide d' ... = error_reporting() à l'intérieur du gestionnaire d'erreur.

La suppression de l'avertissement

Une autre possibilité est de supprimer l'appel avec l'opérateur @ et vérifier la valeur de retour de l' dns_get_record() par la suite. Mais je vous le déconseille ce que les erreurs/alertes sont déclenchées à être manipulés, de ne pas être supprimé.

178voto

Robert Points 121

La solution qui fonctionne vraiment s'est avéré être le réglage de simple gestionnaire d'erreur avec E_WARNING de paramètre, comme ceci:

set_error_handler("warning_handler", E_WARNING);

dns_get_record(...)

function warning_handler($errno, $errstr) { 
// do something
}

34voto

GuruBob Points 163

Soyez prudent avec l'opérateur @ - alors qu'il supprime les avertissements, il supprime également les erreurs fatales. J'ai passé beaucoup de temps à déboguer un problème dans un système où quelqu'un avait écrit @mysql_query ( ' ... ' ), et le problème était que le support de mysql n'a pas été chargé en PHP et il jeta un silencieux erreur fatale. Il sera à l'abri de ces choses qui font partie du coeur de PHP, mais merci de l'utiliser avec soin.

bob@mypc:~$ php -a
Interactive shell

php > echo @something(); // this will just silently die...

Aucune autre sortie - bonne chance de débogage ce!

bob@mypc:~$ php -a
Interactive shell

php > echo something(); // lets try it again but don't suppress the error
PHP Fatal error:  Call to undefined function something() in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
bob@mypc:~$ 

Cette fois, nous pouvons voir pourquoi il a échoué.

+1 pour le réglage du gestionnaire d'erreur - je ne peux pas upvote ce parce que je n'ai pas assez de représentants.

6voto

sdaau Points 6262

Je voulais try/catch un avertissement, mais en même temps garder l'habitude d'avertissement/d'erreur d'enregistrement (par exemple, en /var/log/apache2/error.log); pour lesquels le gestionnaire a pour revenir false. Cependant, depuis le "throw new..." principe interrompt l'exécution, on a alors à faire de la "enveloppez-les dans la fonction" truc, également discutés:

Est-il statique de la façon de lancer une exception en php

Ou, en bref:

  function throwErrorException($errstr = null,$code = null, $errno = null, $errfile = null, $errline = null) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
  }
  function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) {
    return false && throwErrorException($errstr, 0, $errno, $errfile, $errline);
    # error_log("AAA"); # will never run after throw
    /* Do execute PHP internal error handler */
    # return false; # will never run after throw
  }
  ...
  set_error_handler('warning_handler', E_WARNING);
  ...
  try {
    mkdir($path, 0777, true);
  } catch (Exception $e) {
    echo $e->getMessage();
    // ...
  }

EDIT: après avoir regarder de plus près, il s'avère qu'il ne fonctionne pas: le "return false && throwErrorException ..." sera, pour l'essentiel, de ne pas jeter l'exception, et il suffit de vous connecter dans le journal des erreurs; enlever le "false &&", comme dans "return throwErrorException ...", fera l'exception de jeter de travail, mais alors pas du journal dans le error_log... je l'avais toujours garder cette posté, bien que, comme je n'ai pas vu ce comportement documenté ailleurs.

2voto

Rusky Points 701

Vous devriez probablement essayer de se débarrasser de l'avertissement complètement, mais si c'est pas possible, vous pouvez faire précéder l'appel avec @ (c'est à dire @dns_get_record(...)) et ensuite utiliser les informations que vous pouvez obtenir pour savoir si l'avertissement qui s'est passé ou pas.

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