À quoi sert le symbole @ en PHP?

577

J'ai vu des utilisations de @devant certaines fonctions, comme les suivantes:

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

Quelle est l'utilité de ce symbole?

sv_in
la source
3
RichieHindle et Aiden Bell ont donné la bonne réponse, mais comme je ne peux définir qu'une seule réponse comme acceptée, je choisirai la première. Désolé Aiden
sv_in
1
La suppression des erreurs (bien qu'agréables) pourrait entraîner des erreurs lors de la maintenance de la base de code ... stackoverflow.com/a/7116175/282343
dennismonsewicz

Réponses:

636

Il supprime les messages d'erreur - voir Opérateurs de contrôle d'erreur dans le manuel PHP.

RichieHindle
la source
46
C'était un peu un tirage rapide!
Aiden Bell
6
Ouais; jusqu'au deuxième! J'ai dû vérifier les identifiants pour voir qui est arrivé en premier :)
Sampson
3
J'ai eu le temps de corriger mon orthographe de suppression après avoir posté ... et je vous maudis d'avoir amélioré avec un lien en même temps fait rage : P
Aiden Bell
1
Fonctionnalité cool .. Il rend isset()inutile l'utilisation de afin d'éviter les undefined offseterreurs.
WM
470

Il supprime les erreurs.

Voir Opérateurs de contrôle d'erreur dans le manuel:

PHP prend en charge un opérateur de contrôle d'erreur: le signe at (@). Lorsqu'il est ajouté à une expression en PHP, tous les messages d'erreur qui pourraient être générés par cette expression seront ignorés.

Si vous avez défini une fonction de gestionnaire d'erreurs personnalisée avec set_error_handler (), elle sera toujours appelée, mais ce gestionnaire d'erreurs personnalisé peut (et devrait) appeler error_reporting () qui retournera 0 lorsque l'appel qui a déclenché l'erreur a été précédé d'un @ ...

Aiden Bell
la source
157
voté juste parce que l'autre réponse reçoit tout l'amour.
ajacian81
10
19 derrière ... allez les gens battons RichieHindle: P
Aiden Bell
Cette réponse était la première (dans le contexte de qui a répondu en premier).
Mohd Abdul Mujib
227

Le @symbole est l' opérateur de contrôle d'erreur (alias l' opérateur "silence" ou "arrêt"). Il fait en sorte que PHP supprime tous les messages d'erreur (notification, avertissement, fatal, etc.) générés par l'expression associée. Il fonctionne comme un opérateur unaire, par exemple, il a une priorité et une associativité. Voici quelques exemples:

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

Que se passe-t-il exactement si vous utilisez un gestionnaire d'erreurs personnalisé au lieu du gestionnaire d'erreurs PHP standard:

Si vous avez défini une fonction de gestionnaire d'erreurs personnalisée avec set_error_handler (), elle sera toujours appelée, mais ce gestionnaire d'erreurs personnalisé peut (et devrait) appeler error_reporting () qui retournera 0 lorsque l'appel qui a déclenché l'erreur a été précédé d'un @ .

Ceci est illustré dans l'exemple de code suivant:

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"

Le gestionnaire d'erreurs n'a pas vérifié si le @symbole était en vigueur. Le manuel suggère ce qui suit:

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

Notez également que malgré les erreurs cachées, tout gestionnaire d'erreurs personnalisé (défini avec set_error_handler) sera toujours exécuté!

nickf
la source
34

Comme déjà certains l'ont déjà répondu: L' @opérateur supprime toutes les erreurs en PHP, y compris les notifications, les avertissements et même les erreurs critiques.

MAIS: S'il vous plaît, n'utilisez pas du @tout l' opérateur.

Pourquoi?

Eh bien, parce que lorsque vous utilisez l' @opérateur pour supprimer les erreurs, vous ne savez absolument pas par où commencer en cas d'erreur. J'ai déjà eu du "fun" avec le code hérité où certains développeurs utilisaient l' @opérateur assez souvent. Surtout dans des cas comme les opérations sur les fichiers, les appels réseau, etc. Ce sont tous des cas où de nombreux développeurs recommandent l'utilisation de l' @opérateur car cela est parfois hors de portée lorsqu'une erreur se produit ici (par exemple, une API tierce peut être inaccessible, etc. ).

Mais quel est l'intérêt de ne toujours pas l'utiliser? Jetons un coup d'œil sous deux angles:

En tant que développeur: quand@est utilisé, je n'ai absolument aucune idée par où commencer. S'il y a des centaines voire des milliers d'appels de fonction avec@l'erreur, cela pourrait être comme partout. Aucun débogage raisonnable possible dans ce cas. Et même si ce n'est qu'une erreur de tierce partie - alors c'est très bien et vous avez terminé rapidement. ;-) De plus, il est préférable d'ajouter suffisamment de détails au journal des erreurs, afin que les développeurs puissent décider facilement si une entrée de journal est quelque chose qui doit être vérifiée davantage ou s'il s'agit simplement d'un échec de tierce partie qui est hors de portée du développeur.

En tant qu'utilisateur: les utilisateurs ne se soucient pas du tout de la raison d'une erreur ou non. Le logiciel est là pour eux de travailler, de terminer une tâche spécifique, etc. Peu importe si c'est la faute du développeur ou un problème de tierce partie. Surtout pour les utilisateurs, je recommande fortement de consigner toutes les erreurs, même si elles sont hors de portée. Vous remarquerez peut-être qu'une API spécifique est fréquemment hors ligne. Que pouvez-vous faire? Vous pouvez parler à votre partenaire API et s'il n'est pas en mesure de le maintenir stable, vous devriez probablement chercher un autre partenaire.

En bref: vous devez savoir qu'il existe quelque chose comme @(la connaissance est toujours bonne), mais ne l'utilisez pas . De nombreux développeurs (en particulier ceux qui déboguent le code des autres) seront très reconnaissants.

Andreas
la source
1
Certains avertissements ne peuvent être supprimés de manière fiable qu'en utilisant @ (par exemple fopen (), où toute tentative de prédire le résultat est soumis à une condition de concurrence critique), si vous avez du code pour gérer la condition d'erreur de manière plus ordonnée, alors usuig @est la bonne chose à faire faites, cela est particulièrement utile, surtout si vous ne revenez pas text/html(ou similaire) au client. (peut-être de retour image/pngou "json")
Jasen
1
Vous ne devez pas supprimer les avertissements - ils indiquent que vous avez fait quelque chose de mal. Il n'y a aucune condition de concurrence dans laquelle vous ne pouvez pas vérifier ou gérer correctement l'état.
Ryan Rentfro
1
J'ai ce qui suit dans mon code à quelques endroits. if( session_status() == PHP_SESSION_NONE ) session_start(); C'est une application héritée dont j'ai hérité, et il y a des endroits où le script de configuration est appelé plusieurs fois, donc je dois tester. Quel problème, le cas échéant, y aurait-il à utiliser simplement @session_start();?
Stephen R
Si vous savez ce que vous faites et que vous l'utilisez avec parcimonie / stratégie, cela vaut la peine d'être utilisé. @$this->stats['device_os'][$date][$creative_id][$device_id][$operating_system]['clicks']++;est beaucoup mieux que l'alternative d'avoir des contrôles isset à chaque niveau et de le remplir quand ce n'est pas le cas.
dtbarne
1
Donnez-moi une bonne raison pour laquelle ajouter plus de 12 lignes de code et n'ajouter aucune valeur, mais seulement réduire la lisibilité et la brièveté du code vaut la peine de faire autre chose que vous lisez quelque part quelque temps qu'il est "tout simplement sale" et peut-être pouvez-vous changer d'avis.
dtbarne
7

Supposons que nous n'ayons pas utilisé l'opérateur "@" alors notre code ressemblerait à ceci:

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

Et si le fichier que nous essayons d'ouvrir n'est pas trouvé? Il affichera un message d'erreur.

Pour supprimer le message d'erreur, nous utilisons l'opérateur "@" comme:

$fileHandle = @fopen($fileName, $writeAttributes);
Sujeet Kumar
la source
C'est un exemple parfait pour expliquer pourquoi PHP a ce type de @solution de contournement en premier lieu. D'autres langages de programmation ont une gestion des exceptions uniforme pour gérer ce type de scénario stackoverflow.com/questions/1087365
dreftymac
@dreftymac Exactement!
Sujeet Kumar
5

Si l'ouverture échoue, une erreur de niveau E_WARNING est générée. Vous pouvez utiliser @ pour supprimer cet avertissement.

Kishor Singh
la source
5

@ supprime les messages d'erreur.

Il est utilisé dans des extraits de code comme:

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

Si le domaine " http://www.exaple.com " n'est pas accessible, une erreur sera affichée, mais @rien ne sera affiché.

fico7489
la source
1

PHP prend en charge un opérateur de contrôle d'erreur: le signe at (@) . Lorsqu'il est ajouté à une expression en PHP, tous les messages d'erreur qui pourraient être générés par cette expression seront ignorés.

Si vous avez défini une fonction de gestionnaire d'erreurs personnalisée avec set_error_handler()alors elle sera toujours appelée, mais ce gestionnaire d'erreurs personnalisé peut (et devrait) appeler error_reporting()qui reviendra 0lorsque l'appel qui a déclenché l'erreur a été précédé d'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.

?>

Remarque:-

1) L'opérateur @ ne fonctionne que sur les expressions.

2) Une règle générale simple est la suivante: si vous pouvez prendre la valeur de quelque chose, vous pouvez y ajouter l'opérateur @. Par exemple, vous pouvez l'ajouter aux variables, fonctionner et inclure des appels, des constantes, etc. Vous ne pouvez pas l'ajouter à des définitions de fonction ou de classe, ou à des structures conditionnelles telles que if et foreach, etc.

Attention:-

Actuellement, le préfixe d'opérateur de contrôle d'erreur "@" désactivera même le rapport d'erreurs pour les erreurs critiques qui mettront fin à l'exécution du script. Entre autres choses, cela signifie que si vous utilisez "@" pour supprimer les erreurs d'une certaine fonction et qu'elle n'est pas disponible ou a été mal tapée, le script mourra juste là sans aucune indication sur pourquoi.

Ravi Hirani
la source
1

Il vaut peut-être la peine d'ajouter ici qu'il y a quelques pointeurs lors de l'utilisation du @ dont vous devez être conscient, pour un aperçu complet, consultez cet article: http://mstd.eu/index.php/2016/06/30/php- rapid-fire-what-is-the-symbol-used-for-in-php /

  1. Le gestionnaire d'erreurs est toujours déclenché même avec le symbole @ ajouté, cela signifie simplement qu'un niveau d'erreur de 0 est défini, cela devra être géré de manière appropriée dans un gestionnaire d'erreurs personnalisé.

  2. Le fait de prévoir une inclusion avec @ définira toutes les erreurs dans le fichier d'inclusion à un niveau d'erreur de 0

brindille
la source
1

@supprime le message d'erreur généré par la fonction. fopenrenvoie une erreur lorsque le fichier ne se ferme pas. @le symbole fait que l'exécution passe à la ligne suivante même si le fichier n'existe pas. Ma suggestion serait de ne pas l'utiliser dans votre environnement local lorsque vous développez un code PHP.

Logamurugan Pilavadi Santhanam
la source