31 votes

Gestion des erreurs en PHP

Je suis familier avec certaines des bases, mais j'aimerais en savoir plus sur quand et pourquoi la gestion des erreurs (y compris le lancement d'exceptions) devrait être utilisée en PHP, en particulier sur un site ou une application web en ligne. Est-ce quelque chose qui peut être surutilisé et si oui, à quoi ressemble une surutilisation ? Y a-t-il des cas où il ne devrait pas être utilisé ? Par ailleurs, quels sont les problèmes de sécurité courants liés à la gestion des erreurs ?

32voto

Alex Weinstein Points 5839

Une chose à ajouter à ce qui a déjà été dit est qu'il est primordial que vous enregistriez toute erreur dans votre application web dans un journal. De cette façon, comme le suggère Jeff "Coding Horror" Atwood, vous saurez quand vos utilisateurs rencontrent des difficultés avec votre application (au lieu de "leur demander ce qui ne va pas").

Pour ce faire, je recommande le type d'infrastructure suivant :

  • Créez une table "crash" dans votre base de données et un ensemble de classes enveloppes pour signaler les erreurs. Je vous recommande de définir des catégories pour les crashs ("blocage", "sécurité", "erreur/alerte PHP" (vs exception), etc).
  • Dans tout votre code de gestion des erreurs, veillez à enregistrer l'erreur. Cela dépend de la qualité de la construction de l'API (étape précédente). trivial pour enregistrer des crashs si c'est fait correctement.

Crédit supplémentaire : parfois, vos pannes seront des pannes au niveau de la base de données : par exemple, un serveur de base de données en panne, etc. Si c'est le cas, votre infrastructure de journalisation des erreurs (ci-dessus) échouera (vous ne pouvez pas enregistrer le crash dans la base de données parce que le journal essaie d'écrire dans la base de données). Dans ce cas, j'écrirais une logique de basculement dans votre classe wrapper Crash pour soit

  • envoyer un courriel à l'administrateur, ET/OU
  • enregistrer les détails de l'accident dans un fichier de texte brut

Tout cela peut sembler exagéré, mais croyez-moi, cela fait une différence dans l'acceptation de votre demande comme "stable" ou "instable". Cette différence vient du fait que toutes les applications commencent par être instables ou se planter tout le temps, mais les développeurs qui connaissent tous les problèmes de leur application ont une chance de les résoudre.

0 votes

De bons conseils, quelle que soit la plateforme.

0 votes

Bien qu'il s'agisse d'un vieux sujet, je voudrais conseiller de faire attention à l'envoi d'un courriel à l'administrateur, car de nombreux services d'hébergement acceptent une limite de ceux-ci et une erreur dans une boucle pourrait vous causer plusieurs problèmes. Je suis passé par là et j'ai souffert de cela.

0 votes

2017+ il y a maintenant beaucoup de produits SaaS qui vous aident à enregistrer les erreurs, et à obtenir des notifications via Slack, email, etc. à leur sujet. Il suffit de googler "enregistrement des erreurs" et vous en trouverez beaucoup, certains avec des tiers gratuits assez intéressants pour les startups.

24voto

troelskn Points 51966

En gros, les erreurs sont un héritage de PHP, alors que les exceptions sont la façon moderne de traiter les erreurs. La chose la plus simple est de mettre en place un gestionnaire d'erreurs, qui lance une exception. De cette façon, toutes les erreurs sont converties en exceptions, et vous n'avez plus qu'un seul système de gestion des erreurs à gérer. Le code suivant convertira les erreurs en exceptions pour vous :

function exceptions_error_handler($severity, $message, $filename, $lineno) {
  if (error_reporting() == 0) {
    return;
  }
  if (error_reporting() & $severity) {
    throw new ErrorException($message, 0, $severity, $filename, $lineno);
  }
}
set_error_handler('exceptions_error_handler');
error_reporting(E_ALL ^ E_STRICT);

Il existe cependant quelques cas où le code est spécifiquement conçu pour fonctionner avec des erreurs. Par exemple, le schemaValidate méthode de DomDocument soulève des avertissements, lors de la validation d'un document. Si vous convertissez les erreurs en exceptions, la validation s'arrêtera après le premier échec. Parfois, c'est ce que vous voulez, mais lorsque vous validez un document, vous pouvez en fait vouloir todo des échecs. Dans ce cas, vous pouvez installer temporairement un gestionnaire d'erreurs, qui collecte les erreurs. Voici un petit extrait, que j'ai utilisé à cette fin :

class errorhandler_LoggingCaller {
  protected $errors = array();
  function call($callback, $arguments = array()) {
    set_error_handler(array($this, "onError"));
    $orig_error_reporting = error_reporting(E_ALL);
    try {
      $result = call_user_func_array($callback, $arguments);
    } catch (Exception $ex) {
      restore_error_handler();
      error_reporting($orig_error_reporting);
      throw $ex;
    }
    restore_error_handler();
    error_reporting($orig_error_reporting);
    return $result;
  }
  function onError($severity, $message, $file = null, $line = null) {
    $this->errors[] = $message;
  }
  function getErrors() {
    return $this->errors;
  }
  function hasErrors() {
    return count($this->errors) > 0;
  }
}

Et un cas d'utilisation :

$doc = new DomDocument();
$doc->load($xml_filename);
$validation = new errorhandler_LoggingCaller();
$validation->call(
  array($doc, 'schemaValidate'),
  array($xsd_filename));
if ($validation->hasErrors()) {
  var_dump($validation->getErrors());
}

3voto

andy.gurin Points 1516

La meilleure pratique, selon moi, est d'utiliser l'approche suivante : 1. créer un gestionnaire d'erreurs/exceptions 2. le lancer au démarrage de l'application 3. gérez toutes vos erreurs à partir de ce gestionnaire

<?php

class Debug {

    public static setAsErrorHandler() {
         set_error_handler(array(__CLASS__, '__error_handler'));
    }

public static function __error_handler($errcode, $errmsg, $errfile, $errline) {
       if (IN DEV) {
                print on screen
           }
           else if (IN PRO) {
                log and mail
           } 
    }
}

Debug::setAsErrorHandler();

?>

2voto

Teifion Points 20581

Les erreurs non maîtrisées arrêtent le script, rien que cela est une assez bonne raison de les gérer.

En général, vous pouvez utiliser un bloc Try-Catch pour traiter les erreurs.

try
{
    // Code that may error
}
catch (Exception $e)
{
    // Do other stuff if there's an error
}

Si vous voulez empêcher l'affichage du message d'erreur ou d'avertissement sur la page, vous pouvez faire précéder l'appel du signe @ comme suit.

 @mysql_query($query);

Cependant, pour les requêtes, c'est généralement une bonne idée de faire quelque chose comme ça pour avoir une meilleure idée de ce qui se passe.

@mysql_query($query)
    or die('Invalid query: ' . mysql_error() . '<br />Line: ' . __LINE__ . '<br />File: ' . __FILE__ . '<br /><br />');

2 votes

L'utilisation de la fonction mysql_error() ne constitue-t-elle pas un risque pour la sécurité ?

0 votes

Vous pouvez avoir un indicateur dans votre application web qui détermine si vous êtes dans un environnement de test ou de production ; en production, ne montrez pas l'erreur, enregistrez-la simplement. En test, faites les deux.

0 votes

Il est important de noter que, par défaut, la plupart des erreurs PHP n'entraînent pas automatiquement la levée d'une exception, ce qui est nécessaire pour que les blocs try...catch fonctionnent. Vous pouvez utiliser une méthode telle que celle décrite à la page uk.php.net/manual/fr/class.errorexception.php pour transformer les erreurs normales en exceptions.

2voto

The Brawny Man Points 447

Vous devriez utiliser la gestion des erreurs dans les cas où vous n'avez pas de contrôle explicite sur les données sur lesquelles votre script travaille. J'ai tendance à l'utiliser fréquemment par exemple dans des endroits comme la validation de formulaires. Savoir repérer les endroits sujets aux erreurs dans le code demande un peu de pratique : Les plus courants sont après les appels de fonction qui renvoient une valeur, ou lors du traitement des résultats d'une requête de base de données. Vous ne devez jamais supposer que le retour d'une fonction sera ce que vous attendez, et vous devez vous assurer de coder par anticipation. Vous n'êtes pas obligé d'utiliser les blocs try/catch, même s'ils sont utiles. Souvent, vous pouvez vous en sortir avec une simple vérification if/else.

La gestion des erreurs va de pair avec les pratiques de codage sécurisées, car il y a beaucoup d'"erreurs" qui ne provoquent pas le plantage de votre script. Bien qu'il ne s'agisse pas strictement de la gestion des erreurs en soi, addedbytes a une bonne série de 4 articles sur certaines des bases de la programmation PHP sécurisée que vous pouvez trouver ICI . Il y a beaucoup d'autres questions ici sur stackoverflow sur des sujets tels que mysql_real_escape_stringing y Expressions régulières qui peut s'avérer très efficace pour confirmer le contenu des données saisies par l'utilisateur.

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