36 votes

Meilleure façon de gérer les erreurs sur une page php?

Maintenant mes pages ressembler à quelque chose comme ceci:

if($_GET['something'] == 'somevalue')
{
    $output .= 'somecode';

    // make a DB query, fetch a row
    //...
    $row = $stmt->Fetch(PDO::ASSOC);

    if($row != null)
    {
        $output .= 'morecode';

        if(somethingIsOK())
        {
            $output .= 'yet more page output';
        }
        else
        {
            $error = 'something is most definitely not OK.';
        }
    }
    else
    {
        $error = 'the row does not exist.';
    }
}
else
{
    $error = 'something is not a valid value';
}

if($error == '') // no error
{
    //display $output on page
}
else // an error
{
    // display whatever error occurred on the page
}

La façon dont je fais les choses fonctionne, mais il est très lourd et fastidieux pour ce qui est probablement évident: supposons que j'appelle une fonction quelque part au milieu de mon code, ou voulez vérifier la valeur d'une variable, ou de vérifier une DB requête a retourné un résultat valide, et si elle échoue, je veux en sortie une erreur? J'ai fais un autre if/else bloc et déplacer tout le code à l'intérieur du nouveau bloc if. Cela ne semble pas être une façon intelligente de faire les choses.

J'ai lu sur try/catch et ont pensé à mettre tout mon code à l'intérieur d'un rapport d'essai, puis de laisser le code à exécuter séquentiellement sans si/d'autre blocs et si quelque chose échoue il suffit de jeter une exception. De ce que j'ai lu, ce serait d'arrêter l'exécution et de la faire passer directement le bloc catch (un peu comme un échec si l'instruction va aller au bloc else), où j'ai pu alors en sortie le message d'erreur. Mais est-ce acceptable ou d'une norme de pratique?

Quelle est la meilleure manière de gérer les erreurs, mortels ou non, dans une application php qui crée et génère une page HTML? Je ne veux pas mourir juste avec un écran vide, comme ce serait très utilisateur de l'onu-friendly, mais, au contraire, veulent afficher un message dans le corps de la page, permettant encore l'en-tête et pied de page à afficher.

Merci pour vos conseils!!!

35voto

Bart Platak Points 1866

Il y a beaucoup de façons que vous pouvez faire face à cela, et franchement, aucun d'eux n'est intrinsèquement "droit".

Vous aurez à décider pour vous-même, quelle méthode est la plus "confortable" pour vous - c'est toujours une mater de préférences (bien qu'il existe certaines techniques que vous devriez éviter et pour de bonnes raisons).

Cela dépendra beaucoup de la façon dont vous partagez votre logique, cependant j'ai tendance à enfermer l'ensemble du code qui peut retourner des erreurs non fatales à l'intérieur d'une fonction, et d'utiliser une valeur de retour de ladite fonction pour indiquer qu'il y avait une erreur.

Pour les erreurs fatales , j'ai tendance à utiliser des exceptions (avec try-catch blocs).

Maintenant, juste pour être clair:

  • Une erreur non fatale est une erreur que vous pouvez récupérer à partir d' - ce qui signifie que même si quelque chose allait mal, il y a encore un peu de code qui peuvent être exécutées et générer quelques précieux de sortie. Par exemple, si vous voulez obtenir de l'heure actuelle à l'aide NTP protocole, mais le serveur ne répond pas, vous pouvez décider d'utiliser les locaux time fonction et continue à afficher un certain précieuses données à l'utilisateur.
  • Une erreur fatale est une erreur que vous ne seriez pas en mesure de récupérer à partir d' - ce qui signifie que quelque chose de mauvais s'est passé et la seule chose que vous pouvez faire est de dire à votre utilisateur que la page ne peut pas faire ce qu'il avait demandé. Par exemple si vous souhaitez récupérer des données à partir de votre base de données et a obtenu SQL Exception - il n'y a pas de données précieuses pour être affichés et vous pouvez en informer l'utilisateur de ce.

Des Erreurs Non Fatales (à l'aide de la fonction de retour)

Un bon exemple de l'utilisation de la fonction retourne comme un moyen de traiter avec les non-mortelles problèmes serait une fonction qui tente d'afficher le contenu d'un fichier sur la page quand ce n'est pas l'objectif principal de la page (par exemple vous avez une fonction qui affiche des badges, récupérées à partir d'un fichier texte, sur chaque page, je sais que c'est tiré par les cheveux, mais garder avec moi).

function getBadge($file){
    $f = fopen($file,'r');
    if(!$f){
        return null;
    }
    .. do some processing ..
    return $badges;
}

$badges = getBadges('badges.txt');
if(!$badges){
    echo "Cannot display badges.";
} else {
    echo $badges;
}
.. carry on doing whatever page should be doing ..

En fait, la fonction fopen lui-même en est un exemple - , il sera de retour.

Retourne un pointeur de fichier de ressource en cas de succès, ou FALSE en cas d'erreur.


Fatal-Erreurs (à l'aide d'exceptions - try-catch)

Lorsque vous avez un morceau de code qui doit être exécuté parce que c'est exactement ce que l'utilisateur veut (par exemple la lecture de toutes les informations de la base de données et de les afficher à l'utilisateur), vous pouvez utiliser les exceptions. Prenons un exemple très simple, un utilisateur a visité son profil et je voulais voir tous les messages qu'il a (supposons, pour l'instant, ils sont stockés en clair). Vous pourriez avoir une fonction comme:

function getMessages($user){
    $messages = array();
    $f = fopen("messages_$user.txt","r");
    if(!$f){
        throw new Exception("Could not read messages!");
    }
    ... do some processing ...
    return $messages;
}

Et de l'utiliser comme ceci:

try{
    ..do some stuff..
    $messages = getMessages($_SESSION['user'])); //assuming you store username in $_SESSION
    foreach($messages as $msg){
        echo $msg."<br/>";
    }
} catch(Exception $e){
    echo "Sorry, there was an error: ".$e->getMessage();
}

Maintenant, cela pourrait venir dans maniable, si vous aviez un "haut-niveau" script qui exécute tout le code des autres. Cela signifie que, par exemple, dans votre index.php vous suffit:

try{
    .. execute some code, perform some functions ..
} catch(Exception $e){
    echo "Sorry, there was an error: ".$e->getMessage();
}

N'abusez pas des exceptions!

Quoi que vous fassiez, ne jamais utiliser les exceptions comme une façon de vérifier quelque chose, vous pouvez le récupérer à partir. À lire sur une autre question(crédit va à Anton Gogolev pour une très bonne explication sur ce, ainsi que d'autres réponse-ers) pourquoi c'est le cas.

Lectures complémentaires

Maintenant, il n'y a pas de meilleure façon d'apprendre à faire face avec des erreurs que d'essayer plusieurs choses et voir ce qui est bon pour vous. Vous pouvez trouver ci-dessous utiles:

Espérons que cela aide :)

6voto

Voici quelque chose de simple, que je suis une utilisation dans certaines applications sensibles.

Pour les erreurs PHP (sans les erreurs d'exception):

 //top most for any execution path (will throw ErrorException for any error/warning/notice/whatever)..
 set_error_handler(function($nNumber, $strMessage, $strFilePath, $nLineNumber){
      error_log(PHP_EOL.date("Y-m-d H:m:s", time())." ".$strFilePath."#".$nLineNumber.": ".$strMessage.PHP_EOL);
      throw new ErrorException($strMessage, 0, $nNumber, $strFilePath, $nLineNumber);
 });
 error_reporting(-1);

AOP prend en charge jeter PDOExceptions, mais la valeur par défaut est off, de sorte que vous avez à faire cela , afin de ne pas avoir à vérifier chaque requête unique ou exec si il est retourné false. Vous pouvez maintenant extraire de la suite (sans vérification de faux, il ne pourra plus retourner false en cas d'erreur), et il suffit de vérifier si fetch retourné le nombre de lignes (ou false si aucune ligne), ou si un exec a affecté le nombre de lignes.

 $pdoDBHandle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

D'intercepter les exceptions est l'endroit où vous avez un choix à faire en fonction de votre type d'application:

  • pour un site web (ou d'un site web comme interface pour certains app), utilisez la fonction set_exception_handler pour rediriger vers une page d'erreur (n'oubliez pas d'enregistrer le message d'erreur).
  • pour les non sites web (applications, qui vient d'exposer un serveur RPC) utiliser try catch de la manipulation. Définir la classe dérivée à partir d'Exception à utiliser spécifiquement pour les Exceptions qui sont autorisés à "ne pas être pris" (vous sera envoyé avec la réponse RPC). Tous les autres types d'exceptions (les classes) doivent être pris, connecté, réduits au silence et remplacé par "l'extérieur" classe d'Exception avec le message d'erreur "erreur Interne".

Essayez de ne pas utiliser les exceptions pour le retour de la fonction (ou de communication), sauf si c'est la seule option disponible pour vous (et encore revoir un peu plus si c'est vrai).

5voto

Edson Medina Points 2555

C'est beaucoup plus élégant et lisible.

try
{

    if($_GET['something'] != 'somevalue') 
    {
        throw new Exception ('something is not a valid value');
    }


    $output .= 'somecode';

    // make a DB query, fetch a row
    //...
    $row = $stmt->Fetch(PDO::ASSOC);

    if($row == null)
    {
        throw new Exception ('the row does not exist.');
    }


    $output .= 'morecode';


    if(somethingIsOK())
    {
        $output .= 'yet more page output';
    }
    else
    {
        throw new Exception ('something is most definitely not OK.');
    }


    echo $output;

}
catch (Exception $e)
{
    echo $e->getMessage();
}

2voto

uınbɐɥs Points 4070

À l'aide de try-catch est l'un des plus propres solutions que vous pouvez utiliser.

J'ai fait un exemple qui affiche toujours l'en-tête et pied de page lorsqu'une erreur se produit, à l'aide de votre code converti à l' try-catch format:

PHP:

<?php
try {
    $output = array();
    if($_GET['something'] != 'somevalue') throw new Exception('something does not have a valid value.');
    $output[] = 'Some Code';
    $row = mt_rand(0, 10) < 5 ? null : mt_rand(0, 100);
    if($row === null) throw new Exception('The row does not exist.');
    $output[] = $row;
    if(!somethingIsOK()) throw new Exception('Something is most definitely not OK.');
    $output[] = 'Yet more page output';
} catch(Exception $e) {
    $output[] = 'Error: ' . $e->getMessage(); // To show output and error
    $output = array('Error: ' . $e->getMessage()); // To only show error
}
function somethingIsOK() {
    return mt_rand(0, 10) < 5;
}
?>

HTML:

<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <meta charset="UTF-8" />
    <title>PHP Error test</title>
    <style type="text/css">
body {
    background: #eee;
    text-align: center
}
#content {
    padding: 60px
}
#header {
    padding: 30px;
    background: #fff
}
#footer {
    padding: 10px;
    background: #ddd
}
    </style>
</head>
<body>
    <div id="header">Header</div>
    <div id="content">
<?php echo implode('<br />', $output); ?>

    </div>
    <div id="footer">Footer</div>
</body>
</html>

Références:

1voto

CodeTalk Points 1107

AOP erreur de manipulation d'exception pour les requêtes, et vraiment tout code doit être exécuté par le biais de:

try{

}

catch{


}

finally{

}

La raison pour cela est qu'il rend le débogage beaucoup plus facile lorsque vous pouvez localiser à peu près où de longs scripts une erreur se produit

plus d'infos ici: http://php.net/manual/en/language.exceptions.php

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