2009-12-14 23 views

Respuesta

26

Respuesta simple: No se puede. Ver el manual:

Los siguientes tipos de errores no pueden ser manejados con una función definida por el usuario: E_ERROR, E_PARSE, E_CORE_ERROR E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, y la mayoría de E_STRICT criados en el archivo donde set_error_handler() se llama.

Por cada otro error, puede utilizar set_error_handler()

EDIT:

Puesto que parece, que hay algunos debates sobre este tema, en lo que respecta a la utilización de register_shutdown_function, deberíamos echar un vistazo a la definición de manejo: Para mí, manejar un error significa detectar el error y reaccionar de una manera que es "agradable" para el usuario y los datos subyacentes (bases de datos, archivos, servicios web, etc.).

Al usar register_shutdown_function no puede manejar un error dentro del código donde fue llamado, lo que significa que el código aún dejará de funcionar en el punto donde ocurre el error. Sin embargo, puede presentar al usuario un mensaje de error en lugar de una página en blanco, pero no puede, por ejemplo, revertir nada de lo que hizo su código antes de fallar.

+3

En realidad, usted puede manejar esos errores con una función definida por el usuario. Todo lo que tienes que hacer es definir register_shutdown_function. Vea mi respuesta a continuación para obtener un ejemplo de trabajo que implementé en mi sitio web. – jdias

+0

Sí, puedes. Sin embargo, hay algunas desventajas: vea mi edición anterior –

+0

Gracias por la actualización. En realidad, puede hacer más que presentarle al usuario un mensaje de error. Puede registrar los detalles del error, incluidas las variables que se establecieron en el momento en que se produjo el error. Muchas personas que usan alojamiento compartido no tienen acceso a los registros de Apache, por ejemplo. Al usar esta función, podrían registrar errores críticos y abordarlos. Además, puedes intentar recuperar transacciones. Por ejemplo, si el error ocurrió cuando el usuario intentaba realizar un pedido, puede volcar todos los detalles del pedido en un registro o correo electrónico e intentar recuperarlo sin conexión. – jdias

29

Puede realizar un seguimiento de estos errores utilizando el código de la siguiente manera:

(errores de análisis sólo pueden ser capturados si se producen en otros archivos de comandos través include() o require(), o poniendo este código en un auto_prepend_file como otras respuestas ha mencionado.)

function shutdown() { 
    $isError = false; 

    if ($error = error_get_last()){ 
    switch($error['type']){ 
     case E_ERROR: 
     case E_CORE_ERROR: 
     case E_COMPILE_ERROR: 
     case E_USER_ERROR: 
      $isError = true; 
      break; 
     } 
    } 

    if ($isError){ 
     var_dump ($error);//do whatever you need with it 
    } 
} 

register_shutdown_function('shutdown'); 
+7

¿Lo has probado? –

+4

Sí, hay una manera de atrapar E_PARSE! Coloque la función del controlador de errores en index.php e incluya/requiera otro archivo donde debería estar la lógica del sitio. –

+1

La única forma en que pude evitar la visualización de errores de análisis fue incluir el script que contenía el error de análisis. – Melsi

4

La secuencia de comandos con el error de análisis se interrumpe siempre y no se puede manejar. Entonces, si el script se llama directamente o mediante include/require, no hay nada que puedas hacer. Pero si es llamado por AJAX, flash o de cualquier otra forma, hay es una solución alternativa a cómo detectar errores de análisis.

Necesitaba esto para manejar el script swfupload. Swfupload es un flash que se encarga de la carga de archivos y archivo cada vez que se carga, llama la escritura manejo de PHP para manejar filedata - pero no hay salida de navegador, por lo que la secuencia de comandos de manipulación PHP necesita estos ajustes para fines de depuración:

  • advertencias y avisos ob_start(); al principio y almacenar el contenido en sesión por ob_get_contents(); al final de la secuencia de comandos de manipulación: Esto se puede visualizar en el navegador por otro script
  • errores fatales register_shutdown_function() para establecer la sesión con el mismo truco que anteriormente
  • errores de análisis si los ob_get_contents() es ubicado al final de la secuencia de comandos de manejo y el error de análisis anterior, la sesión no se completa (es nula). La depuración de scripts puede manejar de esta manera: if(!isset($_SESSION["swfupload"])) echo "parse error";

Nota 1null significa is not set a isset()

10

De los comentarios PHP.net en la página http://www.php.net/manual/en/function.set-error-handler.php

me he dado cuenta de que una pocas personas aquí mencionaron que no se pueden capturar los errores de análisis (tipo 4, E_PARSE). Esto no es verdad. Así es como lo hago. Espero que esto ayude a alguien.

1) Crear un archivo "auto_prepend.php" en la raíz web y añadir lo siguiente:

<?php 
register_shutdown_function('error_alert'); 

function error_alert() 
{ 
     if(is_null($e = error_get_last()) === false) 
     { 
       mail('[email protected]', 'Error from auto_prepend', print_r($e, true)); 
     } 
} 
?> 

2) A continuación, añadir esta "php_value auto_prepend_file /www/auto_prepend.php" a su .htaccess archivo en la raíz web.

  • asegúrese de cambiar la dirección de correo electrónico y la ruta del archivo.
+0

Esta solución cubre E_PARSE, E_COMPILE_ERROR, etc. Por lo tanto, la respuesta de Dan Soap y el manual de php.net son incorrectos. ¡Gracias! – mgutt

+0

Si está utilizando FastCgi, no puede establecer el valor de PHP en .htaccess. En su lugar, utiliza su archivo local php.ini y establece directamente auto_prepend_file = /www/auto_prepend.php –

61

Actualmente, puede manejar el análisis sintáctico y los errores fatales. Es cierto que no se invocará la función del controlador de errores que definió con set_error_handler(). La forma de hacerlo es definiendo una función de apagado con register_shutdown_function(). Esto es lo que tengo trabajando en mi sitio web:

Archivo prepend.php (este archivo se agregará a todos los scripts de PHP automáticamente). Consulte a continuación para obtener sugerencias sobre cómo anteponer archivos a PHP.

set_error_handler("errorHandler"); 
register_shutdown_function("shutdownHandler"); 

function errorHandler($error_level, $error_message, $error_file, $error_line, $error_context) 
{ 
$error = "lvl: " . $error_level . " | msg:" . $error_message . " | file:" . $error_file . " | ln:" . $error_line; 
switch ($error_level) { 
    case E_ERROR: 
    case E_CORE_ERROR: 
    case E_COMPILE_ERROR: 
    case E_PARSE: 
     mylog($error, "fatal"); 
     break; 
    case E_USER_ERROR: 
    case E_RECOVERABLE_ERROR: 
     mylog($error, "error"); 
     break; 
    case E_WARNING: 
    case E_CORE_WARNING: 
    case E_COMPILE_WARNING: 
    case E_USER_WARNING: 
     mylog($error, "warn"); 
     break; 
    case E_NOTICE: 
    case E_USER_NOTICE: 
     mylog($error, "info"); 
     break; 
    case E_STRICT: 
     mylog($error, "debug"); 
     break; 
    default: 
     mylog($error, "warn"); 
} 
} 

function shutdownHandler() //will be called when php script ends. 
{ 
$lasterror = error_get_last(); 
switch ($lasterror['type']) 
{ 
    case E_ERROR: 
    case E_CORE_ERROR: 
    case E_COMPILE_ERROR: 
    case E_USER_ERROR: 
    case E_RECOVERABLE_ERROR: 
    case E_CORE_WARNING: 
    case E_COMPILE_WARNING: 
    case E_PARSE: 
     $error = "[SHUTDOWN] lvl:" . $lasterror['type'] . " | msg:" . $lasterror['message'] . " | file:" . $lasterror['file'] . " | ln:" . $lasterror['line']; 
     mylog($error, "fatal"); 
} 
} 

function mylog($error, $errlvl) 
{ 
...do whatever you want... 
} 

PHP llamará a la función errorHandler() si detecta un error en cualquiera de los scripts. Si el error obliga al script a cerrar inmediatamente, la función shutdownHandler() maneja el error.

Esto está trabajando en el sitio que tengo en desarrollo. Todavía no lo he probado en producción. Pero actualmente está detectando todos los errores que encuentro al desarrollarlo.

Creo que existe el riesgo de detectar el mismo error dos veces, una vez por cada función.Esto podría suceder si un error que estoy manejando en la función shutdownHandler() también fue capturado por la función errorHandler().

TODO de:

1 - Tengo que trabajar en una mejor función log() para controlar los errores con gracia. Como todavía estoy en desarrollo, básicamente estoy registrando el error en una base de datos y haciéndolo eco en la pantalla.

2 - Implementa el manejo de errores para todas las llamadas MySQL.

3 - Implementar manejo de errores por mi código Javascript.

NOTAS IMPORTANTES:

1 - estoy usando la siguiente línea en mi php.ini para anteponer automáticamente el script de arriba a todos los scripts PHP:

auto_prepend_file = "/homepages/45/d301354504/htdocs/hmsee/cgi-bin/errorhandling.php" 

funciona bien.

2 - estoy tala y la resolución de todos los errores, incluidos los errores E_STRICT. Creo en desarrollar un código limpio. Durante el desarrollo, mi archivo php.ini tiene las siguientes líneas:

track_errors = 1 
display_errors = 1 
error_reporting = 2147483647 
html_errors = 0 

Cuando voy en vivo, que va a cambiar display_errors a 0 para reducir el riesgo de mis usuarios vean mensajes de error feo PHP.

Espero que esto ayude a alguien.

+5

Parece que no maneja "Parse Errors" ... intente lo siguiente: echo "Cat"; echo "Perro" echo "Lion"; – Phantom007

+0

¡Tienes que anteponer el archivo para manejar los errores de análisis! – Dargmuesli

+0

'E_DEPRECATED' y' E_USER_DEPRECATED' también deberían incluirse en la función personalizada del controlador de errores. – Wh1T3h4Ck5

4

Desde mi experiencia se puede tomar todo tipo de errores, ocultar el mensaje de error predeterminado y mostrará un mensaje de error de su cuenta (si lo desea). A continuación se enumeran las cosas que necesita.

1) Un guión inicial/nivel superior, llamémosla index.php donde guardar las funciones de gestor de errores personalizados. Los manejadores de funciones de errores personalizados deben permanecer en la parte superior para que puedan detectar los errores debajo de ellos, me refiero a "debajo" en los archivos inclued.

2) La suposición de que este script de arriba es libre de errores debe ser verdad! esto es muy importante, no puede detectar errores fatales en index.php cuando su función personalizada de controlador de errores se encuentra en index.php.

directivas 3) PHP (también deben ser encontrados en index.php) set_error_handler("myNonFatalErrorHandler"); #in fin de atrapar errores no fatales register_shutdown_function('myShutdown'); #in fin de detectar errores fatales ini_set('display_errors', false); #in fin de ocultar errores que se muestran a usuario por php ini_set('log_errors',FALSE); #assuming registramos los errores de nuestros yoes ini_set('error_reporting', E_ALL); #we desea informar todos los errores

mientras que en la producción (si no estoy equivocado) podemos dejar ini_set('error_reporting', E_ALL); como es con el fin de ser capaz de registrar el error, en el mismo tiempo ini_set('display_errors', false); se asegurará de que n o los errores se muestran al usuario.

En cuanto al contenido real de las dos funciones que estoy hablando, myNonFatalErrorHandler y myShutdown, no pongo contenido detallado aquí para mantener las cosas simples. Además, los otros visitantes han dado muchos ejemplos. Solo muestro una idea muy simple.

function myNonFatalErrorHandler($v, $m, $f, $l, $c){ 
$some_logging_var_arr1[]="format $v, $m, $f, ".$err_lvl[$l].", $c the way you like"; 
//You can display the content of $some_logging_var_arr1 at the end of execution too. 
} 

function myShutdown() 
{ 
    if(($e=error_get_last())!==null){ 
     $some_logging_var_arr2= "Format the way you like:". $err_level[$e['type']].$e['message'].$e['file'].$e['line']; 
    } 
//display $some_logging_var_arr2 now or later, e.g. from a custom session close function 
} 

como para $ err_lvl puede ser:

$err_lvl = array(E_ERROR=>'E_ERROR', E_CORE_ERROR=>'E_CORE_ERROR', E_COMPILE_ERROR=>'E_COMPILE_ERROR', E_USER_ERROR=>'E_USER_ERROR', E_PARSE=>'E_PARSE', E_RECOVERABLE_ERROR=>'E_RECOVERABLE_ERROR', E_WARNING=>'E_WARNING', E_CORE_WARNING=>'E_CORE_WARNING', E_COMPILE_WARNING=>'E_COMPILE_WARNING', 
E_USER_WARNING=>'E_USER_WARNING', E_NOTICE=>'E_NOTICE', E_USER_NOTICE=>'E_USER_NOTICE',E_STRICT=>'E_STRICT'); 
+0

Gracias por agregar que las funciones no pueden estar en el mismo archivo que el error. – Niclas

+0

Mejor utilice un [Cierre] (http://php.net/manual/class.closure.php) como controlador de errores, ya que [las funciones nombradas pueden ser anuladas] (http://php.net/manual/function.override -function.php # 50821) hoy en día – Tino