2008-08-31 17 views
11

Estoy dando el gran salto: ¡mis scripts de PHP fallarán todos!set_error_handler No funciona Cómo quiero que funcione

Al menos, eso es lo que estoy esperando ...

no quiero envolver (prácticamente) cada línea en declaraciones try ... catch, así que creo que mi mejor apuesta es crear un controlador de error personalizado para el comienzo de mis archivos.

estoy prueba a cabo en una página de la práctica:

function customError($level,$message,$file,$line,$context) { 
    echo "Sorry, an error has occured on line $line.<br />"; 
    echo "The function that caused the error says $message.<br />"; 
    die(); 
} 

set_error_handler("customError"); 

echo($imAFakeVariable); 

Esto funciona bien, volviendo:

Sorry, an error has occured on line 17. The function that caused the error says Undefined variable: imAFakeVariable.

Sin embargo, esta configuración no funciona para las funciones definidas.

function customError($level,$message,$file,$line,$context) { 
    echo "Sorry, an error has occured on line $line.<br />"; 
    echo "The function that caused the error says $message.<br />"; 
    die(); 
} 

set_error_handler("customError"); 

imAFakeFunction(); 

Esto devuelve:

Fatal error: Call to undefined function: imafakefunction() in /Library/WebServer/Documents/experimental/errorhandle.php on line 17

¿Por qué no es mi manipulador personalizado poniendo al funciones definidas? ¿Hay otros problemas que esto cause?

Respuesta

9

set_error_handler está diseñado para controlar los errores con códigos de: E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE. Esto se debe a que set_error_handler está destinado a ser un método para informar errores lanzados por usuario error función trigger_error.

Sin embargo, encontré este comentario en el manual que puede ayudarle a:

"The following error types cannot be handled with a user defined function: E_ERROR , E_PARSE , E_CORE_ERROR , E_CORE_WARNING , E_COMPILE_ERROR , E_COMPILE_WARNING , and most of E_STRICT raised in the file where set_error_handler() is called."

This is not exactly true. set_error_handler() can't handle them, but ob_start() can handle at least E_ERROR .

<?php 

function error_handler($output) 
{ 
    $error = error_get_last(); 
    $output = ""; 
    foreach ($error as $info => $string) 
     $output .= "{$info}: {$string}\n"; 
    return $output; 
} 

ob_start('error_handler'); 

will_this_undefined_function_raise_an_error(); 

?> 

Realmente sin embargo estos errores deben ser reportados en silencio en un archivo, por ejemplo. ¡Espero que no tenga muchos errores E_PARSE en su proyecto! :-)

En cuanto a los informes de errores generales, adhiérase a Excepciones (me parece útil hacer que se vinculen con mi sistema MVC). Puede crear una Excepción bastante versátil para proporcionar opciones mediante botones y agregar una gran cantidad de descripción para que el usuario sepa lo que está mal.

1

Why isn't my custom error handler catching undefinedd functions? Are there other problems that this will cause?

Supongo que los errores de función indefinidos viajan a través de una ruta de ejecución diferente a otros tipos de error. Tal vez los diseñadores de PHP podrían decirle más, excepto que dudo que PHP esté diseñado de alguna manera.

Si desea que sus scripts fallen correctamente mientras aún los escribe estilo PHP, intente poner toda la página en una función y luego llámelo dentro de un bloque try..catch.

1

Desde el documentation (énfasis añadido):

The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.

Llamando funciones definidas desencadena un E_ERROR, por lo que no puede ser manejado por la devolución de llamada de error (o por los controladores de excepciones para el caso). Todo lo que puede hacer es establecer error_reporting en 0.

PD, si está ejecutando su propio manejador de errores, debe tener cuidado de manejar correctamente el operador @. De la documentación (énfasis añadido):

It is important to remember that the standard PHP error handler is completely bypassed. error_reporting() settings will have no effect and your error handler will be called regardless - however you are still able to read the current value of error_reporting and act appropriately. Of particular note is that this value will be 0 if the statement that caused the error was prepended by the @ error-control operator.

6

Creo que se tiene que utilizar register_shutdown_function también

Por ejemplo:

register_shutdown_function(array($this, 'customError'));. 

    function customError() 
    { 

    $arrStrErrorInfo = error_get_last(); 

    print_r($arrStrErrorInfo); 

    } 
0

cosa muy interesante que he descubierto hoy como estaba enfrentando el problema similar. Si utiliza la siguiente - se captura el error con la función de controlador de error personalizado/método:

ini_set('display_errors', 'Off'); 
error_reporting(-1); 

set_error_handler(array("Cmd\Exception\Handler", "getError"), -1 & ~E_NOTICE & ~E_USER_NOTICE); 

Al establecer 'display_errors' a 'Off' se puede tomar todavía cogerlos con el controlador.

0

He estado jugando con el manejo de errores durante algún tiempo y parece que funciona en su mayor parte.

function fatalHandler() { 
    global $fatalHandlerError, $fatalHandlerTitle; 

    $fatalHandlerError = error_get_last(); 

    if($fatalHandlerError !== null) { 

     print($fatalHandlerTitle="{$fatalHandlerTitle} | ".join(" | ", $fatalHandlerError). 
       (preg_match("/memory/i", $fatalHandlerError["message"]) ? " | Mem: limit ".ini_get('memory_limit')."/peak ".round(memory_get_peak_usage(true)/(1024*1024))."M" : "")."\n". 
         "GET: ".var_export($_GET,1)."\n". 
         "POST: ".var_export($_POST,1)."\n". 
         "SESSION: ".var_export($_SESSION,1)."\n". 
         "HEADERS: ".var_export(getallheaders(),1)); 
    } 

    return $fatalHandlerTitle; 
} 

function fatalHandlerInit($title="phpError") { 
    global $fatalHandlerError, $fatalHandlerTitle; 

    $fatalHandlerTitle = $title; 
    $fatalHandlerError = error_get_last(); 

    set_error_handler("fatalHandler"); 
} 

Ahora tengo un problema donde si la memoria está agotada, no la informa cada vez. Parece que depende de la cantidad de memoria que se está utilizando. Hice una secuencia de comandos para cargar un archivo grande (lleva ~ 6.6M de memoria) en un bucle infinito. Ajustes 1:

ini_set('memory_limit', '296M'); 

fatalHandlerInit("testing"); 

$file[] = file("large file"); // copy paste a bunch of times 

En este caso me sale el error de ser informes y muere en 45 de carga de archivos.

Configuración2 - igual pero cambio: ini_set ('memory_limit', '299M');

Esta vez no me sale un error y ni siquiera llama a mi función de error personalizado. La secuencia de comandos muere en la misma línea.

¿Alguien tiene una idea de por qué y cómo evitarlo?

Cuestiones relacionadas