Qual è l'uso del simbolo @ in PHP?


577

Ho visto usi di @fronte a determinate funzioni, come le seguenti:

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

A che serve questo simbolo?


3
Sia RichieHindle che Aiden Bell hanno dato la risposta giusta, ma dato che posso impostare una sola risposta come accettata, sceglierò la prima. Siamo spiacenti Aiden
sv_in

1
Sopprimere gli errori (anche se bello) potrebbe causare errori lungo la strada quando il mantenimento della base di codice ... stackoverflow.com/a/7116175/282343
dennismonsewicz

Risposte:


636

Sopprime i messaggi di errore - vedi Operatori di controllo errori nel manuale di PHP.


46
È stato un po 'un pareggio veloce!
Aiden Bell,

6
Si; fino al secondo! Ho dovuto controllare l'id di risposta per vedere chi è arrivato per primo :)
Sampson,

3
Ho avuto il tempo di correggere la mia soppressione dell'ortografia dopo la pubblicazione ... e dannazione per aver migliorato con un link allo stesso tempo infuria : P
Aiden Bell,

1
Funzionalità interessante .. Rende isset()superfluo l ' uso al fine di evitare undefined offseterrori.
WM,

470

Sopprime gli errori.

Vedere Operatori di controllo errori nel manuale:

PHP supporta un operatore di controllo degli errori: il segno at (@). Se anteposto a un'espressione in PHP, tutti i messaggi di errore che potrebbero essere generati da quell'espressione verranno ignorati.

Se hai impostato una funzione del gestore errori personalizzata con set_error_handler () , verrà comunque chiamata, ma questo gestore errori personalizzato può (e dovrebbe) chiamare error_reporting () che restituirà 0 quando la chiamata che ha causato l'errore è stata preceduta da un @ ...


157
votato solo perché l'altra risposta sta ottenendo tutto l'amore.
ajacian81

10
19 dietro ... andiamo gente, battiamo RichieHindle: P
Aiden Bell,

Questa risposta è stata la prima (nel contesto di chi ha risposto per prima).
Mohd Abdul Mujib,

227

Il @simbolo è l' operatore di controllo degli errori (ovvero l' operatore "silenzio" o "arresto"). Fa in modo che PHP elimini qualsiasi messaggio di errore (avviso, avviso, fatale, ecc.) Generato dall'espressione associata. Funziona proprio come un operatore unario, ad esempio, ha una precedenza e associatività. Di seguito sono riportati alcuni esempi:

@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"

Cosa succede esattamente se si utilizza un gestore di errori personalizzato anziché il gestore di errori PHP standard:

Se hai impostato una funzione del gestore errori personalizzata con set_error_handler (), verrà comunque chiamata, ma questo gestore errori personalizzato può (e dovrebbe) chiamare error_reporting () che restituirà 0 quando la chiamata che ha causato l'errore è stata preceduta da un @ .

Questo è illustrato nel seguente esempio di codice:

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"

Il gestore degli errori non ha verificato se il @simbolo era attivo. Il manuale suggerisce quanto segue:

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

58

Si noti inoltre che nonostante gli errori siano nascosti, qualsiasi gestore di errori personalizzato (impostato con set_error_handler) verrà comunque eseguito!


34

Come già alcuni hanno risposto in precedenza: l' @operatore elimina tutti gli errori in PHP, inclusi avvisi, avvertenze e persino errori critici.

MA: Per favore, davvero non usare affatto l' @operatore.

Perché?

Bene, perché quando si utilizza l' @operatore per la soppressione degli errori, non si ha idea di dove iniziare quando si verifica un errore. Mi sono già divertito un po 'con il codice legacy in cui alcuni sviluppatori hanno usato l' @operatore abbastanza spesso. Soprattutto in casi come operazioni sui file, chiamate di rete, ecc. Questi sono tutti casi in cui molti sviluppatori raccomandano l'uso di@ dell'operatore in quanto questo a volte è fuori portata quando si verifica un errore qui (ad esempio un'API di terze parti potrebbe essere irraggiungibile, ecc. ).

Ma qual è il punto di non usarlo ancora? Diamo uno sguardo da due prospettive:

Come sviluppatore: quando@viene utilizzato, non ho assolutamente idea da dove iniziare. Se ci sono centinaia o addirittura migliaia di chiamate di funzione con@l'errore potrebbe essere come ovunque. In questo caso non è possibile eseguire il debug ragionevole. E anche se si tratta solo di un errore di terze parti, allora va bene e il gioco è fatto in fretta. ;-) Inoltre, è meglio aggiungere dettagli sufficienti al registro degli errori, in modo che gli sviluppatori siano in grado di decidere facilmente se una voce di registro è qualcosa che deve essere verificato ulteriormente o se si tratta solo di un errore di terze parti che non rientra nell'ambito dello sviluppatore.

Come utente: utenti non interessa affatto quale sia la ragione di un errore o meno. Il software è lì per loro di funzionare, per completare un compito specifico, ecc. A loro non importa se è colpa dello sviluppatore o un problema di terze parti. Soprattutto per gli utenti, consiglio vivamente di registrare tutti gli errori, anche se non rientrano nell'ambito. Forse noterai che un'API specifica non è in linea frequentemente. Cosa sai fare? Puoi parlare con il tuo partner API e se non sono in grado di mantenerlo stabile, probabilmente dovresti cercare un altro partner.

In breve: dovresti sapere che esiste qualcosa del tipo @(la conoscenza è sempre buona), ma non usarla . Molti sviluppatori (specialmente quelli che eseguono il debug del codice da altri) saranno molto grati.


1
Alcuni avvisi possono essere soppressi in modo affidabile solo usando @ (ad esempio fopen (), dove qualsiasi tentativo di prevedere il risultato è soggetto a una condizione di competizione), se si dispone di un codice per gestire la condizione di errore in modo più ordinato, allora @è la cosa giusta da fare sì, questo è particolarmente utile soprattutto se non stai tornando text/html(o simile) al client. (forse ritornando image/pngo "json")
Jasen,

1
Non dovresti sopprimere gli avvisi: stanno affermando che hai fatto qualcosa di sbagliato. Non ci sono condizioni di gara in cui non è possibile controllare o gestire correttamente lo stato.
Ryan Rentfro,

1
Ho il seguente codice nel mio codice in alcuni punti. if( session_status() == PHP_SESSION_NONE ) session_start(); È un'app legacy che ho ereditato e ci sono luoghi in cui lo script di installazione viene chiamato più volte, quindi devo testarlo. Quale eventuale problema ci sarebbe nel semplice utilizzo @session_start();?
Stephen R,

Se sai cosa stai facendo e lo usi con parsimonia / strategicamente, vale la pena usarlo. @$this->stats['device_os'][$date][$creative_id][$device_id][$operating_system]['clicks']++;è molto meglio dell'alternativa di avere controlli isset per ogni livello e compilarlo quando non lo è.
dtbarne,

1
Dammi una buona ragione per cui vale la pena aggiungere 12+ righe di codice e non aggiungere alcun valore, ma vale la pena solo ridurre la leggibilità e la brevità del codice oltre a quello che hai letto da qualche parte che è "sporco" e forse puoi cambiare idea.
dtbarne,

7

Supponiamo di non aver usato l'operatore "@", quindi il nostro codice sarebbe simile al seguente:

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

E se il file che stiamo tentando di aprire non viene trovato? Mostrerà un messaggio di errore.

Per sopprimere il messaggio di errore stiamo usando l'operatore "@" come:

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

Questo è un esempio perfetto del perché PHP ha questo tipo di @soluzione alternativa in primo luogo. Altri linguaggi di programmazione hanno uniforme gestione delle eccezioni per affrontare questo tipo di scenario stackoverflow.com/questions/1087365
dreftymac

@dreftymac Exactly!
Sujeet Kumar,

5

Se l'apertura non riesce, viene generato un errore di livello E_WARNING. È possibile utilizzare @ per sopprimere questo avviso.


5

@ sopprime i messaggi di errore.

Viene utilizzato nei frammenti di codice come:

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

Se il dominio " http://www.exaple.com " non è accessibile, verrà visualizzato un errore, ma con @nulla non verrà mostrato.


1

PHP supporta un operatore di controllo degli errori: il segno at (@) . Se anteposto a un'espressione in PHP, tutti i messaggi di errore che potrebbero essere generati da quell'espressione verranno ignorati.

Se hai impostato una funzione del gestore degli errori personalizzata con set_error_handler(), verrà comunque chiamata, ma questo gestore degli errori personalizzati può (e dovrebbe) chiamare il error_reporting()quale tornerà 0quando la chiamata che ha innescato l'errore è stata preceduta da un @.

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

?>

Nota:-

1) L'operatore @ funziona solo sulle espressioni.

2) Una semplice regola empirica è: se puoi prendere il valore di qualcosa, puoi anteporre l'operatore @ ad esso. Ad esempio, è possibile anteporre a variabili, funzioni e includere chiamate, costanti e così via. Non è possibile anteporre a definizioni di funzioni o classi o strutture condizionali come if e foreach e così via.

Avvertimento:-

Attualmente il prefisso dell'operatore "@" per il controllo degli errori disabilita persino la segnalazione degli errori critici che interromperanno l'esecuzione dello script. Tra le altre cose, ciò significa che se si utilizza "@" per sopprimere gli errori da una determinata funzione e non è disponibile o è stato digitato in modo errato, lo script morirà lì senza alcuna indicazione sul perché.


1

Potrebbe valere la pena aggiungere qui ci sono alcuni suggerimenti quando si utilizza @ dovresti essere a conoscenza, per una panoramica completa guarda questo post: http://mstd.eu/index.php/2016/06/30/php- fuoco rapido-cosa-è-il-simbolo-usato-per-in-php /

  1. Il gestore errori viene ancora attivato anche con il simbolo @ anteposto, significa solo che è impostato un livello di errore pari a 0, che dovrà essere gestito in modo appropriato in un gestore errori personalizzato.

  2. Se si prepara un'inclusione con @, tutti gli errori nel file di inclusione verranno impostati su un livello di errore pari a 0


1

@sopprime il messaggio di errore generato dalla funzione. fopengenera un errore quando il file non viene chiuso. @il simbolo rende l'esecuzione per passare alla riga successiva anche se il file non esiste. Il mio suggerimento sarebbe di non usarlo nel tuo ambiente locale quando sviluppi un codice PHP.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.