Qual é o uso do símbolo @ no PHP?

577

Eu já vi usos de @na frente de certas funções, como as seguintes:

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

Qual é a utilidade deste símbolo?

sv_in
fonte
3
RichieHindle e Aiden Bell deram a resposta certa, mas como só posso definir uma resposta como aceita, vou escolher a primeira. Desculpe Aiden
sv_in
1
Suprimindo erros (embora bom) poderia causar erros no caminho quando a manutenção da base de código ... stackoverflow.com/a/7116175/282343
dennismonsewicz

Respostas:

636

Suprime mensagens de erro - consulte Operadores de controle de erros no manual do PHP.

RichieHindle
fonte
46
Isso foi um empate rápido!
Aiden Sino
6
Sim; até o segundo! Eu tinha que verificar resposta-id é para ver quem ficou em primeiro lugar :)
Sampson
3
Eu tive tempo para corrigir a minha ortografia suprimir após postagem ... e caramba, para melhorar com um link, ao mesmo tempo se enfurece : P
Aiden Sino
1
Funcionalidade interessante. Torna isset()desnecessário o uso de , a fim de evitar undefined offseterros.
WM
470

Suprime erros.

Consulte Operadores de controle de erros no manual:

O PHP suporta um operador de controle de erro: o sinal de arroba (@). Quando anexado a uma expressão em PHP, qualquer mensagem de erro que possa ser gerada por essa expressão será ignorada.

Se você definiu uma função de manipulador de erro personalizada com set_error_handler () , ela ainda será chamada, mas esse manipulador de erro personalizado pode (e deve) chamar error_reporting () que retornará 0 quando a chamada que acionou o erro foi precedida por um @ ...

Aiden Bell
fonte
157
votado apenas porque a outra resposta está recebendo todo o amor.
ajacian81
10
19 atrás ... vamos lá gente, vamos vencer RichieHindle: P
Aiden Bell
Essa resposta foi a primeira (em contexto com quem a respondeu primeiro).
Mohd Abdul Mujib
227

O @símbolo é o operador de controle de erros (também conhecido como operador "silêncio" ou "desligamento"). Faz com que o PHP suprima qualquer mensagem de erro (aviso, aviso, fatal, etc) gerada pela expressão associada. Funciona como um operador unário, por exemplo, tem precedência e associatividade. Abaixo estão alguns exemplos:

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

O que exatamente acontece se você usar um manipulador de erros personalizado em vez do manipulador de erros PHP padrão:

Se você definiu uma função de manipulador de erro personalizada com set_error_handler (), ela ainda será chamada, mas esse manipulador de erro personalizado pode (e deve) chamar error_reporting () que retornará 0 quando a chamada que acionou o erro foi precedida por um @ .

Isso é ilustrado no seguinte exemplo de código:

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"

O manipulador de erros não verificou se o @símbolo estava em vigor. O manual sugere o seguinte:

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
fonte
58

Observe também que, apesar dos erros serem ocultos, qualquer manipulador de erros personalizado (definido com set_error_handler) ainda será executado!

nickf
fonte
34

Como já respondemos antes: O @operador suprime todos os erros no PHP, incluindo avisos, avisos e até erros críticos.

MAS: Por favor, realmente não use o @operador.

Por quê?

Bem, porque quando você usa o @operador para a supressão de erros, você não tem idéia de onde começar quando ocorrer um erro. Eu já me diverti um pouco com o código legado, onde alguns desenvolvedores usavam o @operador com bastante frequência. Especialmente em casos como operações de arquivo, chamadas de rede, etc. Esses são todos os casos em que muitos desenvolvedores recomendam o uso do @operador, pois isso às vezes fica fora do escopo quando ocorre um erro aqui (por exemplo, uma API de terceiros pode ser inacessível etc.) )

Mas qual é o objetivo de ainda não usá-lo? Vamos dar uma olhada de duas perspectivas:

Como desenvolvedor: quando@é usado, não tenho absolutamente nenhuma idéia por onde começar. Se houver centenas ou mesmo milhares de chamadas de função com@o erro, pode ser como todos os outros. Nenhuma depuração razoável possível neste caso. E mesmo que seja apenas um erro de terceiros - está tudo bem e você termina rápido. ;-) Além disso, é melhor adicionar detalhes suficientes ao log de erros, para que os desenvolvedores possam decidir facilmente se uma entrada de log é algo que deve ser verificado mais a fundo ou se é apenas uma falha de terceiros que está fora do escopo do desenvolvedor.

Como usuário: os usuários não se importam com o motivo ou não do erro. O software existe para que eles trabalhem, concluam uma tarefa específica etc. Eles não se importam se a culpa é do desenvolvedor ou um problema de terceiros. Especialmente para os usuários, recomendo fortemente registrar todos os erros, mesmo que estejam fora do escopo. Talvez você note que uma API específica está off-line com frequência. O que você pode fazer? Você pode conversar com seu parceiro de API e, se ele não conseguir mantê-lo estável, provavelmente deverá procurar outro parceiro.

Em resumo: você deve saber que existe algo como @(o conhecimento é sempre bom), mas simplesmente não o use . Muitos desenvolvedores (especialmente aqueles de depuração de outros) ficarão muito agradecidos.

Andreas
fonte
1
Alguns avisos só podem ser suprimidos de forma confiável usando @ (por exemplo, fopen (), onde qualquer tentativa de prever o resultado está sujeita a uma condição de corrida), se você tiver um código para lidar com a condição de erro de maneira mais organizada, o usuig @é a coisa certa a fazer. isso é especialmente útil, especialmente se você não está retornando text/html(ou similar) ao cliente. (talvez retornando image/pngou "json")
Jasen
1
Você não deve suprimir os avisos - eles estão afirmando que você fez algo errado. Não há condição de corrida em que você não possa verificar ou lidar adequadamente com o estado.
Ryan Rentfro
1
Eu tenho o seguinte no meu código em alguns lugares. if( session_status() == PHP_SESSION_NONE ) session_start(); É um aplicativo herdado que herdei, e há lugares em que o script de instalação é chamado várias vezes, por isso tenho que testar. Qual seria o problema, se houver algum, simplesmente usando @session_start();?
Stephen R
Se você sabe o que está fazendo e o usa com moderação / estratégia, vale a pena usá-lo. @$this->stats['device_os'][$date][$creative_id][$device_id][$operating_system]['clicks']++;é muito melhor do que a alternativa de ter isset checks em cada nível e preenchê-lo quando não estiver.
precisa saber é o seguinte
1
Dê-me uma boa razão pela qual a adição de mais de 12 linhas de código e a adição de nenhum valor, mas apenas a redução da legibilidade e da brevidade do código, vale a pena fazer, exceto se você ler em algum lugar em algum momento que esteja "sujo" e talvez você possa mudar de idéia.
dtbarne
7

Suponha que não tenhamos usado o operador "@", então nosso código ficaria assim:

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

E se o arquivo que estamos tentando abrir não for encontrado? Irá mostrar uma mensagem de erro.

Para suprimir a mensagem de erro, estamos usando o operador "@" como:

$fileHandle = @fopen($fileName, $writeAttributes);
Sujeet Kumar
fonte
Este é um exemplo perfeito de por que o PHP tem esse tipo de @solução alternativa em primeiro lugar. Outras linguagens de programação têm uniforme tratamento de exceção para lidar com este tipo de cenário stackoverflow.com/questions/1087365
dreftymac
@dreftymac Exatamente!
Sujeet Kumar
5

Se a abertura falhar, será gerado um erro do nível E_WARNING. Você pode usar @ para suprimir este aviso.

Kishor Singh
fonte
5

@ suprime mensagens de erro.

É usado em trechos de código como:

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

Se o domínio " http://www.exaple.com " não estiver acessível, um erro será mostrado, mas com @nada não será mostrado.

fico7489
fonte
1

O PHP suporta um operador de controle de erro: o sinal de arroba (@). Quando anexado a uma expressão em PHP, qualquer mensagem de erro que possa ser gerada por essa expressão será ignorada.

Se você definiu uma função de manipulador de erros personalizada set_error_handler(), ela ainda será chamada, mas esse manipulador de erros personalizado pode (e deve) chamar, error_reporting()que retornará 0quando a chamada que acionou o erro foi precedida por um @.

<?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) O operador @ funciona apenas em expressões.

2) Uma regra simples é: se você pode pegar o valor de algo, pode acrescentar o operador @ a ele. Por exemplo, você pode anexá-lo a variáveis, funções e incluir chamadas, constantes e assim por diante. Você não pode anexá-lo a definições de função ou classe, ou estruturas condicionais, como if e foreach, e assim por diante.

Atenção:-

Atualmente, o prefixo do operador de controle de erros "@" desabilita o relatório de erros para erros críticos que encerram a execução do script. Entre outras coisas, isso significa que, se você usar "@" para suprimir erros de uma determinada função e ela não estiver disponível ou tiver sido digitada incorretamente, o script morrerá ali, sem indicação do motivo.

Ravi Hirani
fonte
1

Pode valer a pena adicionar aqui, existem algumas dicas ao usar o @ que você deve conhecer, para uma exibição completa, veja este post: http://mstd.eu/index.php/2016/06/30/php- quick-fire-what-is-the-symbol-used-for-in-php /

  1. O manipulador de erros ainda é acionado, mesmo com o símbolo @ anexado, apenas significa que um nível de erro 0 é definido, e isso deve ser tratado adequadamente em um manipulador de erros personalizado.

  2. Anexar uma inclusão com @ definirá todos os erros no arquivo de inclusão com um nível de erro 0

twigg
fonte
1

@suprime a mensagem de erro lançada pela função. fopengera um erro quando o arquivo não sai. @O símbolo faz a execução passar para a próxima linha, mesmo que o arquivo não exista. Minha sugestão não seria usar isso em seu ambiente local quando você desenvolver um código PHP.

Logamurugan Pilavadi Santhanam
fonte