webentwicklung-frage-antwort-db.com.de

Fehler mit @ Operator in unterdrücken PHP

Ist es Ihrer Meinung nach immer gültig, den Operator @ zu verwenden, um einen Fehler/eine Warnung in PHP zu unterdrücken, während Sie den Fehler behandeln können?

Wenn ja, unter welchen Umständen würden Sie dies verwenden?

Codebeispiele sind willkommen.

Bearbeiten: Hinweis für Replikatoren. Ich möchte die Fehlerberichterstattung nicht deaktivieren, aber es ist zum Beispiel üblich, diese zu verwenden

@fopen($file);

und dann nachprüfen ... aber Sie können das @ loswerden, indem Sie tun

if (file_exists($file))
{
    fopen($file);
}
else
{
    die('File not found');
}

oder ähnliches. 

Ich denke, die Frage ist: Gibt es irgendwo, wo @ benutzt werden muss, um einen Fehler zu unterdrücken, der NICHT auf andere Weise gehandhabt werden kann?

65
Mez

Ich würde den Fehler unterdrücken und damit umgehen . Andernfalls haben Sie möglicherweise einTOCTOUissue (Time-of-Check, Time-of-Use. Zum Beispiel kann eine Datei gelöscht werden, nachdem file_exists true zurückgibt, aber vor fopen).

Aber ich würde Fehler nicht einfach unterdrücken, damit sie verschwinden. Diese sollten besser sichtbar sein.

24
Paweł Hajdan

Hinweis: Erstens stelle ich fest, dass 99% der PHP - Entwickler den Fehlerunterdrückungsoperator verwenden (früher war ich einer von ihnen). Ich erwarte also, dass jeder PHP - Entwickler, der dies sieht, anderer Meinung ist.

Ist es Ihrer Meinung nach immer gültig, den Operator @ zu verwenden, um einen Fehler/eine Warnung in PHP zu unterdrücken, während Sie den Fehler behandeln können?

Kurze Antwort:
Nein!

Länger korrekte Antwort:
Ich weiß es nicht, da ich nicht alles weiß, aber bis jetzt bin ich noch nicht auf eine Situation gestoßen, in der es eine gute Lösung war.

Warum es schlecht ist:
Ich denke, in etwa 7 Jahren mit PHP habe ich jetzt endlose, durch den Fehlerunterdrückungsoperator verursachte Aggressionen gesehen, und bin nie auf eine Situation gestoßen, in der es unvermeidlich war.

Das Problem ist, dass der Code, für den Sie Fehler unterdrücken, momentan nur den Fehler verursacht, den Sie sehen. Wenn Sie jedoch den Code ändern, auf den sich die unterdrückte Zeile bezieht, oder die Umgebung, in der sie ausgeführt wird, besteht die Möglichkeit, dass die Zeile versucht, einen völlig anderen Fehler auszugeben als den, den Sie ignorieren wollten. Wie können Sie dann einen Fehler aufspüren, der nicht ausgegeben wird? Willkommen beim Debuggen der Hölle!

Ich habe viele Jahre gebraucht, um zu realisieren, wie viel Zeit ich wegen unterdrückter Fehler alle paar Monate verschwendete. Am häufigsten (aber nicht ausschließlich) erfolgte dies nach der Installation eines Skripts/einer App/Bibliothek eines Drittanbieters, das in der Entwicklerumgebung fehlerfrei war, jedoch nicht wegen eines Unterschieds zwischen PHP- oder Serverkonfiguration oder fehlender Abhängigkeit, das normalerweise sofort einen Fehler ausgegeben hätte Warnt vor dem Problem, aber nicht, wenn der Entwickler das magische @ hinzufügt.

Die Alternativen (je nach Situation und gewünschtem Ergebnis):
Behandeln Sie den tatsächlichen Fehler, den Sie kennen, so dass ein Code, der einen bestimmten Fehler verursacht, in dieser Situation nicht ausgeführt wird. Aber ich denke, Sie bekommen diesen Teil und Sie waren nur besorgt darüber, dass Endbenutzer Fehler bemerken. Dies ist, was ich jetzt ansprechen werde.

Bei normalen Fehlern können Sie einen Fehlerbehandler einrichten, so dass diese beim Anzeigen der Seite in der von Ihnen gewünschten Weise ausgegeben werden, jedoch für Endbenutzer ausgeblendet und protokolliert werden, sodass Sie wissen, welche Fehler Ihre Benutzer auslösen.

Bei schwerwiegenden Fehlern setzen Sie display_errors in Ihrer php.ini auf "off" (Ihr Fehlerhandler wird immer noch ausgelöst) und aktivieren die Fehlerprotokollierung. Wenn Sie sowohl einen Entwicklungsserver als auch einen Live-Server haben (den ich empfehle), ist dieser Schritt auf Ihrem Entwicklungsserver nicht erforderlich, sodass Sie diese schwerwiegenden Fehler weiterhin debuggen können, ohne sich die Fehlerprotokolldatei ansehen zu müssen. Es gibt sogar einen Trick mit der Shutdown-Funktion , um viele schwerwiegende Fehler an Ihren Fehlerbehandler zu senden.

In Summe:
Bitte vermeiden Sie es. Es mag einen guten Grund dafür geben, aber ich sehe noch keinen, also bin ich bis zu diesem Tag der Meinung, dass der (@) Fehlerunterdrückungsoperator böse ist.

Sie können mein Kommentar zur Seite "Fehlersteuerungsoperatoren" im Handbuch PHP lesen, wenn Sie weitere Informationen wünschen.

113
Gerry

Ja Unterdrückung macht Sinn.

Der Befehl fopen() gibt beispielsweise FALSE zurück, wenn die Datei nicht geöffnet werden kann. Das ist in Ordnung, aber auch erzeugt eine Warnmeldung PHP. Oft möchten Sie die Warnung nicht - Sie werden selbst nach FALSE suchen.

Tatsächlich schlägt das PHP Handbuch in diesem Fall ausdrücklich die Verwendung von @ vor!

19
Jason Cohen

Wenn Sie nicht möchten, dass bei Verwendung von Funktionen wie fopen () eine Warnung ausgegeben wird, können Sie den Fehler unterdrücken, aber Ausnahmen verwenden:

try {
    if (($fp = @fopen($filename, "r")) == false) {
        throw new Exception;
    } else {
        do_file_stuff();
    }
} catch (Exception $e) {
    handle_exception();
}
12
dirtside

Fehlerunterdrückung sollte vermieden werden, es sei denn, Sie wissen , dass Sie mit allen Bedingungen umgehen können.

Dies kann viel schwieriger sein, als es zunächst aussieht.

Was Sie wirklich tun sollten, ist sich darauf zu verlassen, dass "error_log" von PHP Ihre Berichtsmethode ist, da Sie sich nicht darauf verlassen können, dass Benutzer, die Seiten anzeigen, Fehler melden. (Und Sie sollten auch PHP deaktivieren, um diese Fehler anzuzeigen)

Dann haben Sie zumindest einen umfassenden Bericht über alle Fehler im System.

Wenn Sie die Fehler wirklich behandeln müssen, können Sie einen benutzerdefinierten Fehlerbehandler erstellen

http://php.net/set-error-handler

Dann könnten Sie möglicherweise Ausnahmen senden (die behandelt werden können) und alles tun, um der Verwaltung seltsame Fehler zu melden.

6
Kent Fredric

Ich erlaube mir NIEMALS, '@' ... zu verwenden.

Wenn ich die Verwendung von '@' im Code entdecke, füge ich Kommentare hinzu, um es deutlich sichtbar zu machen, sowohl an der Verwendungsstelle als auch im Docblock um die Funktion, in der es verwendet wird. Ich bin auch gebissen worden, weil ein "Geisterjagd" das Debuggen aufgrund dieser Art von Fehlerunterdrückung unterstützt hat, und ich hoffe, es für die nächste Person einfacher zu machen, indem ich deren Verwendung hervorhebe, wenn ich sie finde.

In Fällen, in denen ich möchte, dass mein eigener Code eine Exception auslöst, wenn eine native PHP - Funktion auf einen Fehler stößt und "@" der einfachste Weg zu sein scheint, wähle ich stattdessen etwas anderes, das den gleiches Ergebnis, ist aber im Code (wieder) eklatant:

$orig = error_reporting(); // capture original error level
error_reporting(0);        // suppress all errors
$result = native_func();   // native_func() is expected to return FALSE when it errors
error_reporting($orig);    // restore error reporting to its original level
if (false === $result) { throw new Exception('native_func() failed'); }

Das ist viel mehr Code als nur das Schreiben:

$result = @native_func();

aber ich ziehe es vor, meine Unterdrückung SEHR OBVIOUS zu benötigen, um der armen debuggenen Seele willen, die mir folgt.

6
ashnazg

Die meisten Leute verstehen die Bedeutung der Fehlermeldung nicht.
Im Ernst. Die meisten von ihnen.

Sie denken, dass Fehlermeldungen alle gleich sind, sagt "Etwas geht schief!"
Sie machen sich nicht die Mühe, es zu lesen.
Während es der wichtigste Teil der Fehlermeldung ist - nicht nur die Tatsache, dass es ausgelöst wurde, sondern auch die Bedeutung. Es kann Ihnen sagen, dass was falsch läuft. Fehlermeldungen sind für die Hilfe gedacht, nicht um Sie mit "wie verstecken?" Problem. Dies ist eines der größten Missverständnisse in der Welt der Neulinge im Bereich der Webprogrammierung. 

Anstatt die Fehlermeldung zu würgen, sollte man read was es sagt. Es hat nicht nur einen Wert "Datei nicht gefunden". Es können tausende verschiedene Fehler auftreten: permission denied, save mode restriction, open_basedir restriction usw. etc. Jeder von ihnen erfordert geeignete Maßnahmen. Aber wenn du es würgst, wirst du nie erfahren, was passiert ist!

Das OP verwirrt Fehler Reporting mit Fehler Handling , obwohl es ein sehr großer Unterschied ist!
Fehlerbehandlung gilt für Benutzer. "etwas ist passiert" reicht hier aus.
Während die Fehlerberichterstattung für Programmierer gedacht ist, die unbedingt wissen müssen, was wirklich passiert ist. 

So gag keine Fehlermeldungen. Beide log it für den Programmierer und handhaben für den Benutzer.

5

Der einzige Ort, an dem ich es wirklich brauchte, ist die Eval-Funktion. Das Problem bei eval ist, dass eval nicht falsch zurückgibt, wenn ein String aufgrund eines Syntaxfehlers nicht analysiert werden kann, sondern einen Fehler auslöst, genau wie ein Parserfehler im regulären Skript. Um zu überprüfen, ob das in der Zeichenfolge gespeicherte Skript analysierbar ist, können Sie Folgendes verwenden:

$script_ok = @eval('return true; '.$script);

AFAIK, das ist der eleganteste Weg, dies zu tun.

3
Milan Babuškov

Die Verwendung von @ ist manchmal kontraproduktiv. Nach meiner Erfahrung sollten Sie die Fehlerberichterstattung in der php.ini immer ausschalten oder aufrufen

error_reporting(0);

auf einer Produktionsstätte. Auf diese Weise können Sie in der Entwicklung die Zeile einfach auskommentieren und Fehler für das Debugging sichtbar machen. 

3
Eric Lamb

gibt es keine Möglichkeit, Warnungen und Fehler aus der php.ini zu unterdrücken? In diesem Fall können Sie nur ein Flag debuggen und nicht herausfinden, welches @ das Problem verbirgt.

3
Enrico Murru

Eine Stelle, an der ich es verwende, ist Socket-Code. Wenn Sie beispielsweise ein Timeout festgelegt haben, erhalten Sie eine Warnung, wenn Sie @ nicht angeben, obwohl es zulässig ist, kein Paket zu erhalten.

$data_len = @socket_recvfrom( $sock, $buffer, 512, 0, $remote_Host, $remote_port )
2
Don Neufeld

Sie möchten nicht alles unterdrücken, da es Ihr Skript verlangsamt.

Und ja, es gibt eine Möglichkeit, sowohl in der php.ini als auch in Ihrem Skript Fehler zu entfernen (tun Sie dies jedoch nur, wenn Sie sich in einer Live-Umgebung befinden und Ihre Fehler in php protokollieren)

<?php
    error_reporting(0);
?>

Und Sie können this für die php.ini-Version lesen, um sie auszuschalten.

1
Ólafur Waage

Wenn Sie eine benutzerdefinierte Fehlerbehandlungsfunktion verwenden und einen Fehler (wahrscheinlich einen bekannten Fehler) unterdrücken möchten, verwenden Sie diese Methode. Die Verwendung von '@' ist in diesem Zusammenhang keine gute Idee, da Fehler nicht unterdrückt werden, wenn der Fehlerbehandler festgelegt ist.

Schreibe 3 Funktionen und rufe so an. 

# supress error for this statement
supress_error_start();  
$mail_sent = mail($EmailTo, $Subject, $message,$headers);
supress_error_end(); #Don't forgot to call this to restore error.  

function supress_error_start(){
    set_error_handler('nothing');
    error_reporting(0);
}

function supress_error_end(){
    set_error_handler('my_err_handler');
    error_reporting('Set this to a value of your choice');
}

function nothing(){ #Empty function
}

function my_err_handler('arguments will come here'){
      //Your own error handling routines will come here
}
0
Sumesh

Heute bin ich auf ein Problem gestoßen, das ein gutes Beispiel dafür war, wann man den @-Operator zumindest zeitweise verwenden möchte.

Lange Geschichte, kurz gesagt, fand ich Anmeldeinformationen (Benutzername und Passwort im Klartext) in der Ablaufverfolgung des Fehlerprotokolls.

Hier noch ein paar Infos zu dieser Ausgabe.

Die Anmeldelogik ist eine Klasse für sich, da das System unterschiedliche Anmeldemechanismen bieten soll. Aufgrund von Servermigrationsproblemen ist ein Fehler aufgetreten. Bei diesem Fehler wurde die gesamte Ablaufverfolgung einschließlich der Kennwortinformationen in das Fehlerprotokoll übertragen. Eine Methode erwartete den Benutzernamen und das Kennwort als Parameter. Daher schrieb Trace alles getreu in das Fehlerprotokoll.

Die langfristige Lösung besteht darin, die Klasse umzuwandeln, anstatt Benutzername und Kennwort als 2 Parameter zu verwenden, zum Beispiel einen einzelnen Array-Parameter, der diese beiden Werte enthält (Trace schreibt in solchen Fällen Array für den Parameter aus). Es gibt auch andere Möglichkeiten, dieses Problem anzugehen, aber das ist ein völlig anderes Problem. 

Sowieso. Trace-Nachrichten sind hilfreich, waren aber in diesem Fall völlig schädlich.

Die Lektion, die ich gelernt habe, als ich diese Trace-Ausgabe bemerkte: Manchmal ist das Unterdrücken einer Fehlermeldung vorübergehend eine nützliche Maßnahme, um einen weiteren Zwischenraum zu vermeiden.

Meiner Meinung nach habe ich nicht gedacht, dass es sich um schlechtes Klassendesign handelt. Der Fehler selbst wurde durch eine PDOException ausgelöst (Zeitstempel-Problem, das von MySQL 5.6 auf 5.7 verschoben wurde), das von PHP standardmäßig alles in das Fehlerprotokoll geschrieben hat.

Im Allgemeinen verwende ich den Operator @ nicht für alle in anderen Kommentaren erläuterten Gründe, aber in diesem Fall überzeugte mich das Fehlerprotokoll, etwas schnell zu tun, bis das Problem ordnungsgemäß behoben wurde.

0
Herbert Peters