wake-up-neo.com

Bester Weg, um Fehler auf einer PHP-Seite zu behandeln?

Im Moment sehen meine Seiten ungefähr so ​​aus:

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
}

Die Art und Weise, wie ich die Dinge tue, funktioniert, aber es ist sehr umständlich und mühsam für das, was wahrscheinlich offensichtlich ist: Angenommen, ich rufe eine Funktion irgendwo in der Mitte meines Codes auf oder möchte den Wert einer Variablen überprüfen oder eine DB-Abfrage überprüfen hat ein gültiges Ergebnis zurückgegeben, und wenn es fehlschlägt, möchte ich einen Fehler ausgeben? Ich müsste einen weiteren if/else-Block erstellen und den gesamten Code innerhalb des neuen if-Blocks verschieben. Dies scheint keine kluge Art zu sein, Dinge zu tun.

Ich habe über try/catch gelesen und darüber nachgedacht, meinen gesamten Code in eine try-Anweisung einzufügen, dann den Code nacheinander ohne if/else-Blöcke ausführen zu lassen und wenn etwas fehlschlägt, einfach eine Ausnahme auszulösen. Nach dem, was ich gelesen habe, würde dies die Ausführung anhalten und direkt zum catch-Block springen (genau wie eine fehlgeschlagene if-Anweisung zum else-Block führt), wo ich dann die Fehlermeldung ausgeben könnte. Aber ist das eine akzeptable oder übliche Praxis?

Was ist die beste Methode, um schwerwiegende oder nicht schwerwiegende Fehler in einer PHP-Anwendung zu behandeln, die eine HTML-Seite erstellt und ausgibt? Ich möchte nicht einfach mit einem leeren Bildschirm sterben, da dies sehr benutzerunfreundlich wäre, sondern stattdessen eine Nachricht im Hauptteil der Seite ausgeben und trotzdem die Anzeige von Kopf- und Fußzeile zulassen.

Danke für deinen Rat!

35
Nate

Es gibt viele Möglichkeiten, wie Sie damit umgehen können, und ehrlich gesagt ist keine davon an sich "richtig".

Sie müssen selbst entscheiden, welche Methode für Sie "komfortabler" ist - es ist immer eine Frage der Präferenzen (obwohl es bestimmte Techniken gibt, die Sie aus guten Gründen meiden sollten).

Es hängt stark davon ab, wie Sie Ihre Logik aufteilen, jedoch neige ich dazu, sämtlichen Code einzuschließen, der nicht schwerwiegende Fehler innerhalb einer Funktion zurückgeben kann, und einen Rückgabewert dieser Funktion zu verwenden, um anzuzeigen, dass ein Fehler aufgetreten ist.

Bei fatalen Fehlern neige ich dazu, Ausnahmen (mit try-catch-Blöcken) zu verwenden.

Jetzt nur um klar zu sein:

  • Ein nicht schwerwiegender Fehler ist ein Fehler, mit dem Sie Wiederherstellen von - können - was bedeutet, dass, obwohl etwas schiefgelaufen ist, immer noch Code vorhanden ist, der ausgeführt werden kann und wertvolle Ausgaben generiert. Wenn Sie beispielsweise die aktuelle Uhrzeit mit dem NTP-Protokoll abrufen möchten, der Server jedoch nicht geantwortet hat, können Sie die lokale time-Funktion verwenden und dem Benutzer dennoch einige wertvolle Daten anzeigen.
  • Ein schwerwiegender Fehler ist ein Fehler, bei dem Sie nicht in der Lage wären, Wiederherstellen von - Dies bedeutet, dass etwas wirklich Schlimmes passiert ist, und das einzige, was Sie tun können, ist, Ihrem Benutzer mitzuteilen, dass die Seite nicht das kann, wonach sie gefragt wurde. Wenn Sie zum Beispiel einige Daten aus Ihrer Datenbank abgerufen haben und SQL Exception erhalten haben, können keine wertvollen Daten angezeigt werden, und Sie können den Benutzer nur darüber informieren.

Nicht schwerwiegende Fehler (mit Funktionsrückgabe)

Ein gutes Beispiel für die Verwendung von Funktionsrückgaben als Mittel zur Bewältigung nicht schwerwiegender Probleme wäre eine Funktion, die versucht, den Inhalt einer Datei auf der Seite anzuzeigen wenn dies nicht das Hauptziel der Seite ist (Sie hätten beispielsweise auf jeder einzelnen Seite eine Funktion, die aus einer Textdatei abgerufene Ausweise anzeigt - ich weiß, dass dies weit hergeholt ist, aber ich finde es gut).

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 ..

In der Tat ist die Funktion fopen selbst ein Beispiel dafür - es wird zurückgegeben.

Gibt bei Erfolg eine Dateizeigerressource oder bei Fehler FALSE zurück.


Schwerwiegende Fehler (mit Ausnahmen - try-catch)

Wenn Sie ein Stück Code haben, das ausgeführt werden muss , weil es genau das ist, was der Benutzer wollte (z. B. alle Nachrichten aus der Datenbank lesen und dem Benutzer anzeigen), können Sie Ausnahmen verwenden. Nehmen wir ein einfaches Beispiel - ein Benutzer hat sein Profil besucht und wollte alle Nachrichten sehen, die er erhalten hat (nehmen wir an, dass sie im Klartext gespeichert sind). Möglicherweise haben Sie eine Funktion wie:

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;
}

Und benutze es so:

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();
}

Das könnte sich als nützlich erweisen, wenn Sie ein Skript der obersten Ebene hätten, das den gesamten anderen Code ausführen würde. Das bedeutet, dass Sie beispielsweise in Ihrem index.php nur Folgendes hätten:

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

Ausnahmen nicht überbeanspruchen!

Was auch immer Sie tun, verwenden Sie niemals Ausnahmen, um etwas zu überprüfen, von dem Sie sich erholen können. Lesen Sie zu einer anderen Frage (die volle Anerkennung geht an Anton Gogolev für eine sehr gute Erklärung dazu sowie zu den anderen Antwortern), warum dies der Fall ist.

Lesen Sie weiter

Es gibt keinen besseren Weg, um mit Fehlern umzugehen, als verschiedene Dinge auszuprobieren und zu sehen, was für Sie gut ist. Möglicherweise finden Sie das folgende nützlich:

Hoffe das hilft :)

34
Bart Platak

PHP hat eine eingebaute Klasse, ErrorException , zum Konvertieren von PHP-Fehlern in Ausnahmen, die, wenn sie nicht behandelt werden, die Ausführung natürlich beenden würden. 

Ausnahmen haben Fehlerbehandlungsmechanismen (Try Catch) und bessere Debugging-Informationen (Stack-Traces) verbessert.

Fügen Sie dies ganz oben in Ihrem Ausführungspfad ein (die config oder etwas, das zuerst in Ihrem gesamten Code enthalten ist):

 set_error_handler(function($nNumber, $strMessage, $strFilePath, $nLineNumber){
      throw new \ErrorException($strMessage, 0, $nNumber, $strFilePath, $nLineNumber);
 }, /*E_ALL*/ -1);

PDO unterstützt zwar Ausnahmen, es ist jedoch standardmäßig deaktiviert. Sie müssen es jedoch aktivieren:

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

Wenn Sie MySQL verwenden, möchten Sie auch einen Fehler, wenn Sie keine Pflichtfelder festlegen, und viele andere Fehler/Warnungen, die standardmäßig vergeben werden:

 $pdo->exec("SET sql_mode = 'STRICT_ALL_TABLES'");

Ausnahmen können wie in vielen anderen Programmiersprachen mit try catch finally behandelt werden:

try
{
    echo $iAmAnUndefinedVariable;
}
catch(\Throwable $exception)
{
    /*[...]*/
}

Bei der Validierung von Zeug werden nur Ausnahmen ausgelöst: throw new Exception("Missing URL variable userId!");

Es wäre schön, wenn PHP irgendwann eine saubere Pause von der alten error reporting Sache machen würde und einfach Standardausnahmen werfen würde (deprecate error_reporting () und die Standardeinstellung ändern).

6

Dies ist viel eleganter und lesbarer.

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();
}
5
Edson Medina

try-catch ist eine der saubersten Lösungen, die Sie verwenden können.

Ich habe ein Beispiel erstellt, in dem immer noch die Kopf- und Fußzeile angezeigt wird, wenn ein Fehler auftritt, wobei Ihr Code in das Format try-catch konvertiert wurde:

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>

Referenzen:

2
uınbɐɥs

PDO-Fehlerausnahmebehandlung für Abfragen, und eigentlich sollte der gesamte Code durchlaufen werden:

try{

}

catch{


}

finally{

}

Der Grund dafür ist, dass es das Debuggen erheblich vereinfacht, wenn Sie ungefähr feststellen können, wo in langen Skripts ein Fehler auftritt

weitere Infos hier: http://php.net/manual/de/language.exceptions.php

1
CodeTalk

Erstellen Sie einen Fehlerhandler (set_error_handler) und werfen Sie Ausnahmen hinein.
Es hilft bei Funktionen, die keine Ausnahmen unterstützen.

0
DmitryR

Behandeln Sie PHP Fehler und Warnungen korrekt, indem Sie Fehlerbehandlungsfunktionen verwenden. (Siehe Beispiel hier )

Der beste Weg zur Fehlerbehandlung in PHP ist Sie können alle Fehlerberichte stoppen, indem Sie diese Zeile oben in Ihre PHP-Datei einfügen.

error_reporting(0);

//OR

error_reporting('E_ALL');

// Predefined Constant

Fehlerbehandlung in PHP mit Funktionen:

  • debug_backtrace - Erzeugt eine Rückverfolgung
  • debug_print_backtrace - Druckt einen Backtrace
  • error_clear_last - Löscht den neuesten Fehler
  • error_get_last - Liefert den zuletzt aufgetretenen Fehler
  • error_log - Sendet eine Fehlermeldung an die definierten Fehlerbehandlungsroutinen
  • error_reporting - Legt fest, welche PHP Fehler gemeldet werden
  • restore_error_handler - Stellt die vorherige Fehlerbehandlungsfunktion wieder her
  • restore_exception_handler - Stellt die zuvor definierte Handlerfunktion der Ausnahme wieder her
  • set_error_handler - Legt eine benutzerdefinierte Fehlerbehandlungsfunktion fest
  • set_exception_handler - Legt eine benutzerdefinierte Ausnahmebehandlungsfunktion fest
  • trigger_error - Erzeugt eine Fehlermeldung/Warnung/Benachrichtigung auf Benutzerebene
  • user_error - Alias ​​von trigger_error

Alle Funktionen, die oben aufgeführt sind, werden für die Fehlerbehandlung in PHP verwendet.

0
Steve