Was ist die Verwendung des @ -Symbols in PHP?


577

Ich habe Verwendungen von @vor bestimmten Funktionen gesehen, wie die folgenden:

$fileHandle = @fopen($fileName, $writeAttributes);

Was ist die Verwendung dieses Symbols?


3
Sowohl RichieHindle als auch Aiden Bell gaben die richtige Antwort, aber da ich nur eine Antwort als akzeptiert festlegen kann, werde ich die erste auswählen. Sorry Aiden
sv_in

1
Das Unterdrücken von Fehlern (obwohl nett) kann später zu Fehlern führen, wenn die Codebasis beibehalten wird ... stackoverflow.com/a/7116175/282343
dennismonsewicz

Antworten:


636

Es unterdrückt Fehlermeldungen - siehe Fehlerkontrolloperatoren im PHP-Handbuch.


46
Das war eine schnelle Auslosung!
Aiden Bell

6
Ja; bis zur Sekunde! Ich musste die Antwort-IDs überprüfen, um zu sehen, wer zuerst hereinkam :)
Sampson

3
Ich hatte Zeit , meine Unterdrückungs Rechtschreibung nach Veröffentlichung zu korrigieren ... und verdammt Sie mit einem Link zur gleichen Zeit für die Verbesserung wütet : P
Aiden Glocke

1
Coole Funktion. Es macht die Verwendung von isset()'s unnötig, um undefined offsetFehler zu vermeiden .
WM

470

Es unterdrückt Fehler.

Siehe Fehlerkontrolloperatoren im Handbuch:

PHP unterstützt einen Fehlerkontrolloperator: das at-Zeichen (@). Wenn einem Ausdruck in PHP vorangestellt wird, werden alle Fehlermeldungen, die möglicherweise von diesem Ausdruck generiert werden, ignoriert.

Wenn Sie mit set_error_handler () eine benutzerdefinierte Fehlerbehandlungsfunktion festgelegt haben, wird diese weiterhin aufgerufen. Dieser benutzerdefinierte Fehlerbehandlungsroutine kann (und sollte) jedoch error_reporting () aufrufen, das 0 zurückgibt, wenn dem Aufruf, der den Fehler ausgelöst hat, ein @ vorangestellt wurde ...


157
nur weil die andere Antwort die ganze Liebe bekommt.
Ajacian81

10
19 hinter ... komm schon Leute, lass uns RichieHindle schlagen: P
Aiden Bell

Diese Antwort war die erste (im Zusammenhang mit dem, der sie zuerst beantwortet hat).
Mohd Abdul Mujib

227

Das @Symbol ist der Fehlersteueroperator (auch bekannt als die „Stille“ oder „shut-up“ Operator). Dadurch unterdrückt PHP alle Fehlermeldungen (Hinweis, Warnung, schwerwiegend usw.), die durch den zugehörigen Ausdruck generiert werden. Es funktioniert genau wie ein unärer Operator, zum Beispiel hat es Vorrang und Assoziativität. Nachfolgend einige Beispiele:

@echo 1 / 0;
// generates "Parse error: syntax error, unexpected T_ECHO" since 
// echo is not an expression

echo @(1 / 0);
// suppressed "Warning: Division by zero"

@$i / 0;
// suppressed "Notice: Undefined variable: i"
// displayed "Warning: Division by zero"

@($i / 0);
// suppressed "Notice: Undefined variable: i"
// suppressed "Warning: Division by zero"

$c = @$_POST["a"] + @$_POST["b"];
// suppressed "Notice: Undefined index: a"
// suppressed "Notice: Undefined index: b"

$c = @foobar();
echo "Script was not terminated";
// suppressed "Fatal error: Call to undefined function foobar()"
// however, PHP did not "ignore" the error and terminated the
// script because the error was "fatal"

Was genau passiert, wenn Sie einen benutzerdefinierten Fehlerhandler anstelle des Standard-PHP-Fehlerhandlers verwenden:

Wenn Sie mit set_error_handler () eine benutzerdefinierte Fehlerbehandlungsfunktion festgelegt haben, wird diese weiterhin aufgerufen. Dieser benutzerdefinierte Fehlerbehandlungsroutine kann (und sollte) jedoch error_reporting () aufrufen, das 0 zurückgibt, wenn dem Aufruf, der den Fehler ausgelöst hat, ein @ vorangestellt wurde .

Dies wird im folgenden Codebeispiel veranschaulicht:

function bad_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
    echo "[bad_error_handler]: $errstr";
    return true;
}
set_error_handler("bad_error_handler");
echo @(1 / 0);
// prints "[bad_error_handler]: Division by zero"

Der Fehlerbehandler hat nicht überprüft, ob das @Symbol wirksam ist. Das Handbuch schlägt Folgendes vor:

function better_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
    if(error_reporting() !== 0) {
        echo "[better_error_handler]: $errstr";
    }
    // take appropriate action
    return true;
}

58

Beachten Sie auch, dass trotz ausgeblendeter Fehler jeder benutzerdefinierte Fehlerbehandler (festgelegt mit set_error_handler) weiterhin ausgeführt wird!


34

Wie bereits einige zuvor beantwortet: Der @Bediener unterdrückt alle Fehler in PHP, einschließlich Hinweisen, Warnungen und sogar kritischen Fehlern.

ABER: Bitte benutzen Sie den @Operator überhaupt nicht.

Warum?

Nun, wenn Sie den @Operator zur Fehlerunterdrückung verwenden, haben Sie überhaupt keine Ahnung, wo Sie anfangen sollen, wenn ein Fehler auftritt. Ich hatte bereits etwas "Spaß" mit Legacy-Code, bei dem einige Entwickler den @Operator ziemlich oft verwendeten. Insbesondere in Fällen wie Dateivorgängen, Netzwerkaufrufen usw. In all diesen Fällen empfehlen viele Entwickler die Verwendung des @Operators, da dies manchmal nicht möglich ist, wenn hier ein Fehler auftritt (z. B. kann eine Drittanbieter-API nicht erreichbar sein usw.). ).

Aber was bringt es, es immer noch nicht zu benutzen? Schauen wir uns zwei Perspektiven an:

Als Entwickler: Wann@verwendet wird, habe ich absolut keine Ahnung, wo ich anfangen soll. Wenn es Hunderte oder sogar Tausende von Funktionsaufrufen mit@dem Fehler gibt, könnte dies wie überall sein. In diesem Fall ist kein angemessenes Debugging möglich. Und selbst wenn es sich nur um einen Fehler eines Drittanbieters handelt, ist dies in Ordnung und Sie sind schnell fertig. ;-) Außerdem ist es besser, dem Fehlerprotokoll genügend Details hinzuzufügen, damit Entwickler leicht entscheiden können, ob ein Protokolleintrag weiter geprüft werden muss oder ob es sich nur um einen Fehler eines Drittanbieters handelt, der außerhalb des Anwendungsbereichs des Entwicklers liegt.

Als Benutzer: Benutzern ist es egal, was der Grund für einen Fehler ist oder nicht. Software ist für sie da, um zu arbeiten, eine bestimmte Aufgabe zu erledigen usw. Es ist ihnen egal, ob es die Schuld des Entwicklers oder ein Problem eines Drittanbieters ist. Insbesondere für die Benutzer empfehle ich dringend, alle Fehler zu protokollieren, auch wenn sie außerhalb des Gültigkeitsbereichs liegen. Vielleicht werden Sie feststellen, dass eine bestimmte API häufig offline ist. Was kannst du tun? Sie können mit Ihrem API-Partner sprechen. Wenn dieser nicht in der Lage ist, ihn stabil zu halten, sollten Sie wahrscheinlich nach einem anderen Partner suchen.

Kurz gesagt: Sie sollten wissen, dass es so etwas gibt @(Wissen ist immer gut), aber verwenden Sie es einfach nicht . Viele Entwickler (insbesondere diejenigen, die Code von anderen debuggen) werden sehr dankbar sein.


1
Einige Warnungen können nur mit @ zuverlässig unterdrückt werden (z. B. fopen (), wenn jeder Versuch, das Ergebnis vorherzusagen, einer Rennbedingung unterliegt). Wenn Sie Code haben, um die Fehlerbedingung ordentlicher zu behandeln, @ist usuig das Richtige Dies ist besonders nützlich, insbesondere wenn Sie nicht text/html(oder ähnlich) zum Client zurückkehren. (vielleicht zurück image/pngoder "json")
Jasen

1
Sie sollten Warnungen nicht unterdrücken - sie besagen, dass Sie etwas falsch gemacht haben. Es gibt keine Rennbedingung, in der Sie den Zustand nicht richtig überprüfen oder handhaben können.
Ryan Rentfro

1
Ich habe an einigen Stellen Folgendes in meinem Code. if( session_status() == PHP_SESSION_NONE ) session_start(); Es ist eine Legacy-App, die ich geerbt habe, und es gibt Stellen, an denen das Setup-Skript mehrmals aufgerufen wird, sodass ich es testen muss. Was, wenn überhaupt, wäre ein Problem bei der einfachen Verwendung @session_start();?
Stephen R

Wenn Sie wissen, was Sie tun, und es sparsam / strategisch einsetzen, lohnt es sich, es zu verwenden. @$this->stats['device_os'][$date][$creative_id][$device_id][$operating_system]['clicks']++;ist viel besser als die Alternative, auf jeder Ebene Ausstellungsschecks zu haben und diese auszufüllen, wenn dies nicht der Fall ist.
dtbarne

1
Geben Sie mir einen guten Grund, warum es sich lohnt, mehr als 12 Codezeilen hinzuzufügen und keinen Wert hinzuzufügen, sondern nur die Lesbarkeit und Kürze des Codes zu verringern, außer dass Sie irgendwann irgendwo gelesen haben, dass es "einfach schmutzig" ist, und vielleicht können Sie meine Meinung ändern.
dtbarne

7

Angenommen, wir haben den Operator "@" nicht verwendet, dann würde unser Code folgendermaßen aussehen:

$fileHandle = fopen($fileName, $writeAttributes);

Und was ist, wenn die Datei, die wir öffnen möchten, nicht gefunden wird? Es wird eine Fehlermeldung angezeigt.

Um die Fehlermeldung zu unterdrücken, verwenden wir den Operator "@" wie folgt:

$fileHandle = @fopen($fileName, $writeAttributes);

Dies ist ein perfektes Beispiel dafür, warum PHP diese Art von @Problemumgehung überhaupt hat. Andere Programmiersprachen haben eine einheitliche Ausnahmebehandlung , um mit dieser Art von Szenario umzugehen. Stackoverflow.com/questions/1087365
dreftymac

@dreftymac Genau!
Sujeet Kumar

5

Wenn das Öffnen fehlschlägt, wird ein Fehler der Stufe E_WARNING generiert. Sie können @ verwenden, um diese Warnung zu unterdrücken.


5

@ unterdrückt Fehlermeldungen.

Es wird in Codefragmenten verwendet wie:

@file_get_contents('http://www.exaple.com');

Wenn auf die Domain " http://www.exaple.com " nicht zugegriffen werden kann, wird ein Fehler angezeigt, aber @nichts wird nicht angezeigt .


1

PHP unterstützt einen Fehlerkontrolloperator: das at-Zeichen (@). Wenn einem Ausdruck in PHP vorangestellt wird, werden alle Fehlermeldungen, die möglicherweise von diesem Ausdruck generiert werden, ignoriert.

Wenn Sie eine benutzerdefinierte Fehlerbehandlungsfunktion mit festgelegt set_error_handler()haben, wird diese weiterhin aufgerufen, aber diese benutzerdefinierte Fehlerbehandlungsfunktion kann (und sollte) aufrufen, error_reporting()die zurückgegeben wird, 0wenn dem Aufruf, der den Fehler ausgelöst hat, ein vorangestellt wurde @.

<?php
/* Intentional file error */
$my_file = @file ('non_existent_file') or
    die ("Failed opening file: error was '$php_errormsg'");

// this works for any expression, not just functions:
$value = @$cache[$key];
// will not issue a notice if the index $key doesn't exist.

?>

Hinweis:-

1) Der @ -Operator arbeitet nur mit Ausdrücken.

2) Eine einfache Faustregel lautet: Wenn Sie den Wert von etwas annehmen können, können Sie ihm den Operator @ voranstellen. Sie können es beispielsweise Variablen voranstellen, Aufrufe, Konstanten usw. ausführen und einschließen. Sie können es nicht vor Funktions- oder Klassendefinitionen oder bedingte Strukturen wie if und foreach usw. stellen.

Warnung:-

Derzeit deaktiviert das Präfix "@" für den Fehlerkontrolloperator sogar die Fehlerberichterstattung für kritische Fehler, die die Skriptausführung beenden. Dies bedeutet unter anderem, dass das Skript genau dort stirbt, wenn Sie "@" verwenden, um Fehler einer bestimmten Funktion zu unterdrücken, und diese entweder nicht verfügbar sind oder falsch geschrieben wurden, ohne dass angegeben wird, warum.


1

Es könnte sich lohnen, hier einige Hinweise hinzuzufügen, wenn Sie das @ verwenden, das Sie beachten sollten. Für eine vollständige Übersicht sehen Sie diesen Beitrag: http://mstd.eu/index.php/2016/06/30/php- Schnellfeuer-was-ist-das-Symbol-für-in-PHP verwendet /

  1. Der Fehlerhandler wird auch mit dem vorangestellten @ -Symbol noch ausgelöst. Dies bedeutet lediglich, dass eine Fehlerstufe von 0 festgelegt ist. Dies muss in einem benutzerdefinierten Fehlerhandler entsprechend behandelt werden.

  2. Wenn Sie ein Include mit @ voranstellen, werden alle Fehler in der Include-Datei auf eine Fehlerstufe von 0 gesetzt


1

@unterdrückt die von der Funktion ausgelöste Fehlermeldung. fopenlöst einen Fehler aus, wenn die Datei nicht beendet wird. @Das Symbol bewirkt, dass die Ausführung in die nächste Zeile verschoben wird, auch wenn die Datei nicht vorhanden ist. Mein Vorschlag wäre, dies nicht in Ihrer lokalen Umgebung zu verwenden, wenn Sie einen PHP-Code entwickeln.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.