2008-09-25 17 views
60

En su opinión, ¿es siempre válido usar el operador @ para suprimir un error/advertencia en PHP mientras que usted puede estar manejando el error?Suprimir el error con el operador @ en PHP

Si es así, ¿en qué circunstancias usaría esto?

Ejemplos de código son bienvenidos.

Editar: Nota para los replicantes. No estoy en busca de convertir el informe de errores fuera, pero, por ejemplo, la práctica común es utilizar

@fopen($file); 

y después comprobar después ... pero usted puede deshacerse de la @ haciendo

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

o similar.

Supongo que la pregunta es: ¿hay alguna parte que @ tenga que usarse para suprimir un error, que NO PUEDE manejarse de ninguna otra manera?

+6

Su ejemplo no funciona; "Archivo no encontrado" no es la única forma en que fopen() puede fallar. Quizás el archivo no sea legible. Tal vez está abierto por otro proceso. Las condiciones de error dependen de la plataforma y, de todos modos, es posible que no desee perder tiempo pensando en casos de error. –

+0

ver también: http://stackoverflow.com/questions/1087365 – dreftymac

+4

y ¿por qué se cierra esta pregunta? – GOD

Respuesta

23

que suprimiría el error y manejarlo . De lo contrario, puede tener un problema TOCTOU (tiempo de comprobación, tiempo de uso. Por ejemplo, un archivo puede eliminarse después de que file_exists devuelve true, pero antes fopen).

Pero no me limitaría a suprimir los errores para que desaparezcan. Estos serán mejores visibles.

+8

El problema es que terminas suprimiendo otros errores que no predijo y luego te pasas todo el día intentando rastrear un error que no arroja ningún error. En la rara situación de un problema de TOCTOU, creo que es mucho mejor lanzar un error, ya que los errores de PHP no se deben mostrar a los usuarios finales de todos modos, pero de todos modos permitirá que alguien se dé cuenta de la situación al registrar errores o mostrar si la secuencia de comandos se ejecuta en un entorno de desarrollo. La supresión de errores es la mejor manera de ocultar un problema. (por ejemplo, archivos que se eliminan :)) – Gerry

+5

Esto está bien, pero por el amor de no ser perseguido y asesinado, por favor verifique el error correcto. Una vez pasé demasiado tiempo rastreando un problema de base de datos: estaba viendo fallas de Close() y nada funcionaba. Eventualmente descubrí que la conexión inicial genious @ 'd, y la verificación de "else" estaban esencialmente vacías. Al quitar el @, pude discernir inmediatamente que las credenciales de conexión eran malas. –

19

Sí supresión tiene sentido.

Por ejemplo, el comando fopen() devuelve FALSE si el archivo no se puede abrir. Está bien, pero también produce un mensaje de advertencia de PHP. A menudo no quieres la advertencia: verificarás el FALSE tú mismo.

De hecho, el PHP manual sugiere específicamente usar @ en este caso.

+3

pero, seguramente, esto se puede evitar verificando file_exists ($ file) primero? – Mez

+14

No, no puede, existen otras condiciones de error como "sin permisos para leer" o "archivo ocupado". –

+3

Eso es genial hasta que fopen arroje un error que no estabas anticipando. No puede verificar todas sus condiciones de error conocidas? Crea una función de envoltura fopen. – Gerry

3

¿No hay forma de evitar las advertencias y los errores de php.ini? en ese caso puede depurar solo cambiando un marcador y no tratando de descubrir cuál @ está ocultando el problema.

+0

sí, puede hacer error_reporting (E_ALL & ~ E_NOTICE & ~ E_WARNING) - pero no quiero hacer esto, vea la pregunta editada – Mez

1

No desea suprimir todo, ya que ralentiza su secuencia de comandos.

Y sí hay una manera tanto en php.ini y dentro de su script para eliminar errores (pero sólo hacerlo cuando se está en un entorno real y registrar sus errores de php)

<?php 
    error_reporting(0); 
?> 

Y usted puede leer this para la versión php.ini de apagarlo.

+0

No estoy buscando una manera de desactivarlo, estoy buscando si hay una razón para usarlo, como en cualquier cosa que no se pueda manejar sin usar @ (un elemento hasta ahora - mysql_connect) – Mez

+0

¡Hola! ¿Qué hace que sea más lento el guión? ¡Gracias! – Industrial

+0

@Industrial está haciendo un trabajo extra para suprimir los errores. Como se supone que muestra un error, pero encuentra un @ allí y tiene que lidiar con él de forma dinámica. –

6

Se debe evitar la supresión de errores a menos que conozca puede manejar todas las condiciones.

Esto puede ser mucho más difícil de lo que parece al principio.

Lo que realmente debe hacer es confiar en el "error_log" de php como su método de informe, ya que no puede confiar en que los usuarios vean las páginas para informar errores. (Y también debe deshabilitar php para que no muestre estos errores)

Entonces, al menos, tendrá un informe completo de todas las cosas que fallan en el sistema.

Si realmente tiene que manejar los errores, puede crear un controlador de errores personalizado

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

Entonces usted podría enviar excepciones (que pueden ser manejados) y hacer lo necesario para reportar errores extraños a la administración .

+0

Sé que no debería suprimir los errores, pero algunas cosas arrojarán un E_WARNING o un E_NOTICE, cuando no es necesario mostrarlo al usuario final, y en muchos casos, puede evitarse realmente estos . excepto, por ahora en el caso de mysql_open – Mez

+1

@martin meredith: es por eso que utilizas "error_log" y "display_errors = false" –

+0

@Kent - ¡La mejor respuesta en esta página! [edit: haz el segundo mejor, porque acabo de agregar uno: P] @Mez - Como Kent ha sugerido, configura un controlador de errores que solo te muestra errores. – Gerry

-1

Lo uso cuando intento cargar un archivo HTML para procesarlo como un objeto DOMDocument. Si hay algún problema en el HTML ... y qué sitio web no tiene al menos un ... DOMDocument-> loadHTMLFile() arrojará un error si no lo suprime con @. Esta es la única forma (tal vez hay otras mejores). He tenido éxito al crear raspadores HTML en PHP.

3

Usar @ a veces es contraproducente. En mi experiencia, siempre debe desactivar el informe de errores en php.ini o llamar al

error_reporting(0); 

en un sitio de producción. De esta manera, cuando esté en desarrollo, puede comentar la línea y mantener los errores visibles para la depuración.

+0

Prefiero que los errores sean visibles. Lo que estoy tratando de resolver, si hay alguna forma de que deba usar un @ o podría tener un error, que no puede ser capturado antes. – Mez

+0

Nunca he visto una instancia en la que usar @ para la supresión de errores fuera algo positivo. Oculta todos los errores futuros, no solo el que desea ignorar. – Gerry

+0

No apague error_reporting, ¡eso es una locura! Mientras lo vuelve a encender, asegúrese de que pueda registrar errores en un archivo que pueda leer más adelante. La forma correcta de no mostrar errores a los usuarios es a través de 'ini_set ('display_errors', 0);' o mejor aún, modifique directamente el archivo ini para incluir eso. –

2

Un lugar donde lo uso está en el código del socket, por ejemplo, si tiene un tiempo de espera establecido, recibirá una advertencia si no incluye @, aunque es válido para no obtener un paquete.

$data_len = @socket_recvfrom($sock, $buffer, 512, 0, $remote_host, $remote_port) 
10

Si no desea una advertencia lanzada al utilizar funciones como fopen(), puede suprimir el error pero el uso de excepciones:

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

Este es mi método preferido – MattBelanger

+3

Si está lanzando una excepción, entonces no necesita estrictamente el 'else', solo' do_file_stuff() '. – MrWhite

111

Nota: En primer lugar, me doy cuenta de que el 99% de los desarrolladores de PHP usan el operador de supresión de errores (solía ser uno de ellos), así que estoy esperando que cualquier desarrollador de PHP lo vea en desacuerdo.

En su opinión, ¿es siempre válido utilizar el operador @ para suprimir un error/advertencia en PHP mientras que usted puede estar manejando el error?

Respuesta corta:
No!

más larga respuesta más correcta:
no sé como yo no lo sé todo, pero hasta ahora no me he encontrado con una situación en la que era una buena solución.

Por qué es malo:
En lo que creo que es de aproximadamente 7 años usando PHP ahora he visto agonía sin fin depuración causado por el operador supresión de errores y nunca he encontrado con una situación en la que era inevitable.

El problema es que la pieza de código para la que está suprimiendo los errores, actualmente solo puede causar el error que está viendo; sin embargo, cuando cambia el código en el que se basa la línea suprimida, o el entorno en el que se ejecuta, entonces hay muchas posibilidades de que la línea intente generar un error completamente diferente al que estaba tratando de ignorar. Entonces, ¿cómo rastrear un error que no está dando salida? Bienvenido a depurar el infierno!

Me tomó muchos años darme cuenta de cuánto tiempo estaba perdiendo cada dos meses debido a errores suprimidos. Muy a menudo (pero no exclusivamente) esto fue después de instalar un script/aplicación/biblioteca de un tercero que no contenía errores en el entorno de desarrolladores, pero no mía debido a una diferencia de configuración de servidor o php o dependencia faltante que normalmente generaría un error inmediatamente alertando sobre el problema, pero no cuando el desarrollador agrega la magia @.

Las alternativas (dependiendo de la situación y resultado deseado):
controlar el error real que usted está enterado de, por lo que si una pieza de código va a causar un cierto error entonces no se ejecuta en esa situación particular. Pero creo que obtienes esta parte y te preocupaba que los usuarios finales vean errores, que es lo que ahora abordaré.

Para los errores habituales, puede configurar un manejador de errores para que salgan de la forma que desee cuando está viendo la página, pero ocultos para los usuarios finales y registrados, para saber qué errores están desencadenando los usuarios.

En los errores fatales, configure display_errors como desactivado (su manejador de errores aún se desencadena) en su php.ini y habilite el registro de errores. Si tiene un servidor de desarrollo, así como un servidor en vivo (que recomiendo), este paso no es necesario en su servidor de desarrollo, por lo que aún puede depurar estos errores fatales sin tener que recurrir a buscar el archivo de registro de errores. Incluso hay un trick using the shutdown function para enviar una gran cantidad de errores fatales a su controlador de errores.

En resumen:
Por favor, evitarlo. Puede haber una buena razón para ello, pero todavía tengo que ver uno, por lo que hasta ese día es mi opinión que el operador de supresión de errores (@) es malo.

Puede leer my comment on the Error Control Operators page en el manual de PHP si desea más información.

+20

Esto es absolutamente correcto. Suprimir los errores es un error fundamental. Use su controlador de errores, o use excepciones, no oculte el error. – MattBelanger

+0

Incluso "isset" es más rápido que "@", aún prefiero usar "@": $_LOG_TYPES=array('request', 'click'); $t1=time().substr(microtime(),2,6); for ($i=0;$i<10000;++$i) {$log_type=in_array(@$_GET['log_type'], $_LOG_TYPES)?$_GET['log_type']:'unknown'; } $t2=time().substr(microtime(),2,6); echo 'time_length:'.((float)$t2-(float)$t1); $t1=time().substr(microtime(),2,6); for ($i=0;$i<10000;++$i) {$log_type=in_array(isset($_GET['log_type'])?$_GET['log_type']:null, $_LOG_TYPES)?$log_type:'unknown'; } $t2=time().substr(microtime(),2,6); echo 'time_length:'.((float)$t2-(float)$t1); diyism

+11

'-1' para repetir un meme tonto" es malo ". Evitar una función de lenguaje incorporada con una indiferencia explícita para el caso de uso real es la definición principal de la programación de culto a la carga. - En particular, esta diatriba no menciona que los errores suprimidos no desaparecen. Un manejador de error personalizado todavía puede revivirlos ('set_error_handler (" var_dump ");' es un equivalente perezoso de la extensión de grito). Además, tales advertencias demasiado amplias conducen a las soluciones comunes de sintaxis de supresión de notificaciones 'isset()', que en realidad pueden obstruir la depuración (ya que los avisos de depuración se suprimen irremediablemente). – mario

6

NUNCA me permito usar '@' ... period.

Cuando descubro el uso de '@' en el código, agrego comentarios para hacerlo más evidente, tanto en el punto de uso como en el docblock alrededor de la función donde se usa. A mí también me ha picado la depuración de "perseguir a un fantasma" debido a este tipo de supresión de errores, y espero que sea más fácil para la siguiente persona al resaltar su uso cuando lo encuentre.

En los casos en que deseo que mi propio código arroje una excepción si una función nativa de PHP encuentra un error, y '@' parece ser la manera más fácil de hacerlo, prefiero hacer otra cosa que consiga la mismo resultado, pero es (de nuevo) salta a la vista en el código:

$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'); } 

eso es mucho más código que acaba de escribir:

$result = @native_func(); 

pero prefiero hacer mi supresión necesita muy obvio, en aras del pobre alma depuradora que me sigue.

+1

Esta es una opinión y no muy buena. Puede lograr lo mismo con $ result = @native_func(); y si ($ resultado) sin ese lío feo culo. Estoy de acuerdo @ es malo, pero solo si no se maneja. – Mfoo

+0

¿Crees que es más kosher que @fopen? También deshabilita el informe de errores pero con más código y mayor tiempo de ejecución. Intento IIRC ... la captura no funcionará porque está advirtiendo, no por error ... intente ... la captura será una solución kosher en este caso. Está ocultando la advertencia de NetBeans solamente ... – 18C

+0

El problema que trato de resolver aquí es resaltar al siguiente desarrollador que se está haciendo la supresión. Elijo sacrificar las líneas de código, el tiempo de ejecución micro optimizado y la presunta fealdad para lograr mi objetivo. No veo una "mejor manera" que cubra todas las necesidades, así que así es como elijo mis intercambios. – ashnazg

3

El único lugar donde realmente necesitaba usarlo es la función eval. El problema con eval es que, cuando la cadena no se puede analizar debido a un error de sintaxis, eval no devuelve falso, sino que arroja un error, al igual que tener un error de análisis en el script normal. Con el fin de comprobar si la secuencia de comandos almacenado en la cadena es analizable se puede usar algo como:

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

yo sepa, esta es la manera más elegante de hacer esto.

+0

En primer lugar, eval() no debería usarse nunca. En segundo lugar, si $ script contiene funciones, éstas se evaluarán y la segunda vez que se ejecute, se quejará de que esas funciones ya se definieron y terminaron. –

0

Si está utilizando una función personalizada de manejo de errores y quiere suprimir un error (probablemente un error conocido), utilice este método. El uso de '@' no es una buena idea en este contexto, ya que no suprimirá el error si se configura el manejador de errores.

Escriba 3 funciones y llame de esta manera.

# 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 
} 
4

La mayoría de las personas no entiende el significado del mensaje de error.
No es broma. La mayoría de ellos.

Ellos piensan que los mensajes de error son todos iguales, dice "¡Algo va mal!"
No se molestan en leerlo.
Si bien es la parte más importante del mensaje de error, no solo el hecho de que se ha planteado, sino su significado. Puede decirle lo que está fallando. Los mensajes de error son de ayuda, no para molestarlo con "¿cómo ocultarlo?" problema. Ese es uno de los mayores malentendidos en el mundo de la programación web para novatos.

Por lo tanto, en lugar de mensaje de error de amordazamiento, uno debe leer lo que dice. No tiene solo un valor de "archivo no encontrado". Puede haber miles de errores diferentes: permission denied, save mode restriction, open_basedir restriction etc.etc. Cada uno requiere acción apropiada. ¡Pero si lo amordazas nunca sabrás lo que sucedió!

El PO está arruinando error informes con el error manejo, mientras que es muy grande la diferencia!
El manejo de errores es para el usuario. "algo pasó" es suficiente aquí.
Si bien los informes de errores son para programadores, quienes necesitan saber qué pasó con certeza.

Por lo tanto, nunca gag mensajes de error. Ambos lo registran para el programador, y lo manejan para el usuario.

Cuestiones relacionadas