2011-10-21 13 views
10

Tengo un script con un manejador de excepciones. Este manejador de excepciones limpia un par de conexiones, antes de que el script salga después de una excepción.Excepción de lanzamiento dentro del controlador de excepciones

Me gustaría volver a lanzar la excepción de este manejador de excepciones para que sea manejado por el manejador de excepciones de último recurso de PHP, donde el error se escribe en el registro de errores de PHP, o cualquiera que sea el predeterminado, configurado en PHP.ini.

Desafortunadamente, esto no parece ser una posibilidad, como se indica aquí:

http://www.php.net/manual/en/function.set-exception-handler.php#68712

Will cause a Fatal error: Exception thrown without a stack frame

¿Hay otra forma de burbuja que el error en la pila para que PHP maneja después de mi excepción controlador ha terminado de limpiar?

+0

el uso de un manejador de excepción personalizada seguirá siendo desencadenar un erro fatal r y así registrar el error. – netcoder

+0

¿Por qué no [acaba de lanzar la excepción nuevamente] (http://stackoverflow.com/questions/7856173/throwing-exception-within-exception-handler/7939492#7939492) desde su controlador? Funciona si sabes cómo. Y activará el controlador de último recurso de PHP que está buscando. – hakre

+0

He visto esto antes (y recomendaría restaurar el controlador de errores) pero no puedo reproducirlo ahora mismo. ¿Es este problema parcial a una versión de la configuración de PHP/.ini? – jlb

Respuesta

12

No se puede volver a lanzar desde el controlador de excepción, sin embargo, hay otros lugares que puede. Por ejemplo, puede desacoplar el relanzamiento desde el controlador mediante la encapsulación de cosas en una clase de su propia y luego utilizar la función __destruct() (PHP 5.3, Demo):

<?php 

class ExceptionHandler 
{ 
    private $rethrow; 
    public function __construct() 
    { 
     set_exception_handler(array($this, 'handler')); 
    } 
    public function handler($exception) 
    { 
     echo "cleaning up.\n"; 
     $this->rethrow = $exception; 
    } 
    public function __destruct() 
    { 
     if ($this->rethrow) throw $this->rethrow; 
    } 
} 

$handler = new ExceptionHandler; 

throw new Exception(); 

poner esto en mi registro de errores:

[29-Oct-2011 xx:32:25] PHP Fatal error: Uncaught exception 'Exception' in /.../test-exception.php:23 
Stack trace: 
#0 {main} 
thrown in /.../test-exception.php on line 23 
+1

Véase también, algo relacionado con el '__destruct': [¿Cómo determinar si un script PHP está en fase de finalización?] (Http://stackoverflow.com/q/6227611/367456) – hakre

+0

Gracias @hakre, su la solucion funciona Más de una solución de lo que esperaba, pero entiendo por qué es necesario. – Brad

+0

Hola Brad, gracias por la aceptación. Me gusta más esta "solución" que la sugerencia sobre los comentarios de los usuarios en php.net para crear la entrada del registro de errores en los propios. ¿Por qué reinventar la rueda? Lo intenté también con la función de apagado de registro, pero este de aquí me gusta más. – hakre

6

Simplemente tome la excepción y registre el mensaje usted mismo, luego vuelva a lanzar.

try { 
    $foo->doSomethingToCauseException(); 
} catch (Exception $e) { 
    error_log($e->getMessage()); 
    throw $e; 
} 

Si suben a la parte superior y PHP es incapaz de manejar, el resultado será una excepción no capturada.

+0

Una excepción no detectada estaría bien conmigo. Quiero burbujear todo hasta la cima.Estoy registrando el error en este momento (usando el método exacto que está describiendo), pero prefiero dejar que PHP lo maneje, por coherencia. – Brad

+0

Ya veo. Tengo curiosidad por esto también. En mi experiencia, la única forma en que PHP maneja las excepciones es causando que la página explote, jajaja. –

3

Will cause a Fatal error: Exception thrown without a stack frame

Este error significa que su excepción proviene de un código que no forma parte del script (por lo que PHP conoce). Los ejemplos de dicho código incluyen el manejador de excepciones personalizado establecido con set_exception_handler() y cualquier método de destrucción de clases. No hay más remedio que NO arrojar una excepción de dicho código.

Si desea el manejo de errores nativos de PHP, le sugiero que llame al trigger_error() en su lugar. Debería registrar el error si no tiene un controlador de errores personalizado y utiliza el tipo de error adecuado. Por ejemplo, E_USER_ERROR debería estar bien.

+0

O [simplemente eche la excepción de nuevo] (http://stackoverflow.com/questions/7856173/throwing-exception-within-exception-handler/7939492#7939492) que, dependiendo de la configuración, dará la traza inversa adecuada. – hakre

+0

hakre: simplemente pruébalo (arroje * cualquier cosa * desde dentro de un manejador de excepción personalizado o método destructor de clase) - encontrará que no funciona. No importa si usas xdebug o no. –

+1

Mikko, parece que [mi respuesta] (http://stackoverflow.com/questions/7856173/throwing-exception-within-exception-handler/7939492#7939492) requiere PHP 5.3. Ver también http://codepad.viper-7.com/jamrqP – hakre

1

Sólo volver a lanzar la excepción como una RuntimeException y que se mantendrá la StackTrace :)

try { 
    // bad exception throwing code 
} catch (Exception $e) { 
    throw new RuntimeException($e->getMessage(), $e->getCode(), $e); 
} 
Cuestiones relacionadas