try strip_tags remove new exceptions ejemplo custom catch all php fatal-error

strip_tags - try catch php 7



¿Cómo puedo detectar un error fatal de PHP? (18)

Puedo usar set_error_handler() para detectar la mayoría de los errores de PHP, pero no funciona para errores fatales ( E_ERROR ), como llamar a una función que no existe. ¿Hay otra manera de atrapar estos errores?

Estoy intentando llamar a mail() para todos los errores y estoy ejecutando PHP 5.2.3.


Buena solución encontrada en Zend Framework 2:

/** * ErrorHandler that can be used to catch internal PHP errors * and convert to an ErrorException instance. */ abstract class ErrorHandler { /** * Active stack * * @var array */ protected static $stack = array(); /** * Check if this error handler is active * * @return bool */ public static function started() { return (bool) static::getNestedLevel(); } /** * Get the current nested level * * @return int */ public static function getNestedLevel() { return count(static::$stack); } /** * Starting the error handler * * @param int $errorLevel */ public static function start($errorLevel = /E_WARNING) { if (!static::$stack) { set_error_handler(array(get_called_class(), ''addError''), $errorLevel); } static::$stack[] = null; } /** * Stopping the error handler * * @param bool $throw Throw the ErrorException if any * @return null|ErrorException * @throws ErrorException If an error has been catched and $throw is true */ public static function stop($throw = false) { $errorException = null; if (static::$stack) { $errorException = array_pop(static::$stack); if (!static::$stack) { restore_error_handler(); } if ($errorException && $throw) { throw $errorException; } } return $errorException; } /** * Stop all active handler * * @return void */ public static function clean() { if (static::$stack) { restore_error_handler(); } static::$stack = array(); } /** * Add an error to the stack * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @return void */ public static function addError($errno, $errstr = '''', $errfile = '''', $errline = 0) { $stack = & static::$stack[count(static::$stack) - 1]; $stack = new ErrorException($errstr, 0, $errno, $errfile, $errline, $stack); } }

Esta clase le permite iniciar el ErrorHandler específico a veces si lo necesita. Y luego también puede detener el controlador.

Utilice esta clase, por ejemplo, de esta manera:

ErrorHandler::start(E_WARNING); $return = call_function_raises_E_WARNING(); if ($innerException = ErrorHandler::stop()) { throw new Exception(''Special Exception Text'', 0, $innerException); } // or ErrorHandler::stop(true); // directly throws an Exception;

Enlace al código completo de la clase:
https://github.com/zendframework/zf2/blob/master/library/Zend/Stdlib/ErrorHandler.php


Una solución tal vez mejor es la de Monolog :

Enlace al código completo de la clase:
https://github.com/Seldaek/monolog/blob/master/src/Monolog/ErrorHandler.php

También puede manejar FATAL_ERRORS usando la función register_shutdown_function . De acuerdo con esta clase, un FATAL_ERROR es uno de los siguientes array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR) .

class ErrorHandler { // [...] public function registerExceptionHandler($level = null, $callPrevious = true) { $prev = set_exception_handler(array($this, ''handleException'')); $this->uncaughtExceptionLevel = $level; if ($callPrevious && $prev) { $this->previousExceptionHandler = $prev; } } public function registerErrorHandler(array $levelMap = array(), $callPrevious = true, $errorTypes = -1) { $prev = set_error_handler(array($this, ''handleError''), $errorTypes); $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap); if ($callPrevious) { $this->previousErrorHandler = $prev ?: true; } } public function registerFatalHandler($level = null, $reservedMemorySize = 20) { register_shutdown_function(array($this, ''handleFatalError'')); $this->reservedMemory = str_repeat('' '', 1024 * $reservedMemorySize); $this->fatalLevel = $level; } // [...] }


¡Desarrollé una forma de capturar todos los tipos de error en PHP (casi todos)! No estoy seguro de E_CORE_ERROR (creo que no funcionará solo para ese error)! ¡Pero, para otros errores fatales (E_ERROR, E_PARSE, E_COMPILE ...) funciona bien usando solo una función de control de errores! Ahí va mi solución:

Coloque este código siguiente en su archivo principal (index.php):

<?php define(''E_FATAL'', E_ERROR | E_USER_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR); define(''ENV'', ''dev''); //Custom error handling vars define(''DISPLAY_ERRORS'', TRUE); define(''ERROR_REPORTING'', E_ALL | E_STRICT); define(''LOG_ERRORS'', TRUE); register_shutdown_function(''shut''); set_error_handler(''handler''); //Function to catch no user error handler function errors... function shut(){ $error = error_get_last(); if($error && ($error[''type''] & E_FATAL)){ handler($error[''type''], $error[''message''], $error[''file''], $error[''line'']); } } function handler( $errno, $errstr, $errfile, $errline ) { switch ($errno){ case E_ERROR: // 1 // $typestr = ''E_ERROR''; break; case E_WARNING: // 2 // $typestr = ''E_WARNING''; break; case E_PARSE: // 4 // $typestr = ''E_PARSE''; break; case E_NOTICE: // 8 // $typestr = ''E_NOTICE''; break; case E_CORE_ERROR: // 16 // $typestr = ''E_CORE_ERROR''; break; case E_CORE_WARNING: // 32 // $typestr = ''E_CORE_WARNING''; break; case E_COMPILE_ERROR: // 64 // $typestr = ''E_COMPILE_ERROR''; break; case E_CORE_WARNING: // 128 // $typestr = ''E_COMPILE_WARNING''; break; case E_USER_ERROR: // 256 // $typestr = ''E_USER_ERROR''; break; case E_USER_WARNING: // 512 // $typestr = ''E_USER_WARNING''; break; case E_USER_NOTICE: // 1024 // $typestr = ''E_USER_NOTICE''; break; case E_STRICT: // 2048 // $typestr = ''E_STRICT''; break; case E_RECOVERABLE_ERROR: // 4096 // $typestr = ''E_RECOVERABLE_ERROR''; break; case E_DEPRECATED: // 8192 // $typestr = ''E_DEPRECATED''; break; case E_USER_DEPRECATED: // 16384 // $typestr = ''E_USER_DEPRECATED''; break; } $message = ''<b>''.$typestr.'': </b>''.$errstr.'' in <b>''.$errfile.''</b> on line <b>''.$errline.''</b><br/>''; if(($errno & E_FATAL) && ENV === ''production''){ header(''Location: 500.html''); header(''Status: 500 Internal Server Error''); } if(!($errno & ERROR_REPORTING)) return; if(DISPLAY_ERRORS) printf(''%s'', $message); //Logging error on php file error log... if(LOG_ERRORS) error_log(strip_tags($message), 0); } ob_start(); @include ''content.php''; ob_end_flush(); ?>

Espero que esto ayude a muchas personas! ¡Estaba buscando esta solución por mucho tiempo y no la encontré! ¡Entonces desarrollé uno!


Bueno, parece posible detectar errores fatales de otra manera :)

ob_start(''fatal_error_handler''); function fatal_error_handler($buffer){ $error=error_get_last(); if($error[''type''] == 1){ // type, message, file, line $newBuffer=''<html><header><title>Fatal Error </title></header> <style> .error_content{ background: ghostwhite; vertical-align: middle; margin:0 auto; padding:10px; width:50%; } .error_content label{color: red;font-family: Georgia;font-size: 16pt;font-style: italic;} .error_content ul li{ background: none repeat scroll 0 0 FloralWhite; border: 1px solid AliceBlue; display: block; font-family: monospace; padding: 2%; text-align: left; } </style> <body style="text-align: center;"> <div class="error_content"> <label >Fatal Error </label> <ul> <li><b>Line</b> ''.$error[''line''].''</li> <li><b>Message</b> ''.$error[''message''].''</li> <li><b>File</b> ''.$error[''file''].''</li> </ul> <a href="javascript:history.back()"> Back </a> </div> </body></html>''; return $newBuffer; } return $buffer; }


Desarrollé esta función para hacer posible el código de "caja de arena" que podría causar un error fatal. Dado que las excepciones lanzadas desde el cierre register_shutdown_function no se emiten desde la pila de llamadas de error pre-fatal, me veo obligado a salir después de esta función para proporcionar una forma uniforme de usarla.

function superTryCatchFinallyAndExit( Closure $try, Closure $catch = NULL, Closure $finally ) { $finished = FALSE; register_shutdown_function( function() use ( &$finished, $catch, $finally ) { if( ! $finished ) { $finished = TRUE; print "EXPLODE!".PHP_EOL; if( $catch ) { superTryCatchFinallyAndExit( function() use ( $catch ) { $catch( new Exception( "Fatal Error!!!" ) ); }, NULL, $finally ); } else { $finally(); } } } ); try { $try(); } catch( Exception $e ) { if( $catch ) { try { $catch( $e ); } catch( Exception $e ) {} } } $finished = TRUE; $finally(); exit(); }


Escribí una sesión de preguntas y respuestas estilo Wiki con una solución completa para detectar todos los errores en PHP; que se puede ver / recoger / robar / criticar here .

La solución incluye 5 métodos que envuelven todos los errores que PHP puede generar, que eventualmente pasarán dichos errores hasta un objeto escrito ''ErrorHandler''.

Espero que algunas personas le den algo de utilidad. Incluso si no lo roba directamente, estoy seguro de que la solución es al menos un buen ejemplo de cómo manejar los errores en PHP, en todos los aspectos.

@Lucas Batistussi obtuvo puntos por creatividad. Me imagino que también podría compartir mi solución y buscar algunos puntos similares ...


Hay ciertas circunstancias en las que incluso los errores fatales deben ser detectados (es posible que tenga que hacer un poco de limpieza antes de salir con gracia y no acaba de morir ...). He implementado un gancho de pre_sistema en mis aplicaciones de codeigniter para poder obtener mis errores fatales a través de correos electrónicos, y esto me ayudó a encontrar errores que no se informaron (o se informaron después de que se solucionaron, como ya sabía sobre ellos :)). Verifique si el error ya ha sido reportado para que no le envíe spam con errores conocidos varias veces.

class PHPFatalError { public function setHandler() { register_shutdown_function(''handleShutdown''); } } function handleShutdown() { if (($error = error_get_last())) { ob_start(); echo "<pre>"; var_dump($error); echo "</pre>"; $message = ob_get_clean(); sendEmail($message); ob_start(); echo ''{"status":"error","message":"Internal application error!"}''; ob_flush(); exit(); } }


Los errores fatales o los errores fatales recuperables ahora generan instancias de Error en PHP 7 o versiones superiores . Al igual que cualquier otra excepción, los objetos de Error se pueden capturar utilizando un bloque try/catch .

Ejemplo:

<?php $variable = ''not an object''; try { $variable->method(); // Throws an Error object in PHP 7 or higger. } catch (Error $e) { // Handle error echo $e->getMessage(); // Call to a member function method() on string }

https://3v4l.org/67vbk

O puede usar la interfaz Throwable para capturar todas las excepciones.

Ejemplo:

<?php try { undefinedFunctionCall(); } catch (Throwable $e) { // Handle error echo $e->getMessage(); // Call to undefined function undefinedFunctionCall() }

https://3v4l.org/Br0MG

Para más información: http://php.net/manual/en/language.errors.php7.php


Necesito manejar errores fatales para que una producción muestre en su lugar una salida HTML 508 de Servicio no disponible con un estilo estático. Este es sin duda un enfoque razonable para "atrapar errores fatales". Esto es lo que he hecho:

Tengo una función de manejo de errores personalizada "error_handler" que mostrará mi página HTML "Servicio 503 no disponible" en cualquier E_ERROR, E_USER_ERROR, etc. Ahora se llamará a la función de apagado, detectando mi error fatal.

function fatal_error_handler() { if (@is_array($e = @error_get_last())) { $code = isset($e[''type'']) ? $e[''type''] : 0; $msg = isset($e[''message'']) ? $e[''message''] : ''''; $file = isset($e[''file'']) ? $e[''file''] : ''''; $line = isset($e[''line'']) ? $e[''line''] : ''''; if ($code>0) error_handler($code,$msg,$file,$line); } } set_error_handler("error_handler"); register_shutdown_function(''fatal_error_handler'');

en mi función personalizada custom_handler, si el error es E_ERROR o E_USER_ERROR, etc. también llamo a @ob_end_clean (); para vaciar el búfer, eliminando así el mensaje "error fatal" de PHP.

Tome nota importante de las estrictas funciones de verificación isset () y @ silencing ya que no queremos que nuestros scripts error_handler generen ningún error.

Al estar aún de acuerdo con keparo, la captura de errores fatales anula el propósito del "error FATAL", por lo que no está realmente destinado a que hagas más procesamiento. No ejecute ninguna función de correo () en este proceso de cierre, ya que seguramente realizará una copia de seguridad del servidor de correo o de su bandeja de entrada. En su lugar, registre estos eventos para archivar y programar un cron para encontrar estos archivos de error.log y enviarlos por correo a los administradores.


No puede detectar / manejar errores fatales, pero puede registrarlos / informarlos. Para una rápida depuración modifiqué una respuesta a este simple código.

function __fatalHandler() { $error = error_get_last(); //check if it''s a core/fatal error, otherwise it''s a normal shutdown if ($error !== NULL && in_array($error[''type''], array(E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING,E_RECOVERABLE_ERROR))) { echo "<pre>fatal error:/n"; print_r($error); echo "</pre>"; die; } } register_shutdown_function(''__fatalHandler'');


No puedes lanzar una excepción dentro de la función de apagado registrada de esa manera:

<?php function shutdown() { if (($error = error_get_last())) { ob_clean(); throw new Exception("fatal error"); } } try { $x = null; $x->method() } catch(Exception $e) { # this won''t work } ?>

Pero puede capturar y redirigir la solicitud a otra página.

<?php function shutdown() { if (($error = error_get_last())) { ob_clean(); # raport the event, send email etc. header("Location: http://localhost/error-capture"); # from /error-capture, you can use another redirect, to e.g. home page } } register_shutdown_function(''shutdown''); $x = null; $x->method() ?>


PHP no proporciona medios convencionales para atrapar y recuperarse de errores fatales. Esto se debe a que el procesamiento normalmente no debe recuperarse después de un error fatal. La cadena que coincide con un búfer de salida (como lo sugiere la publicación original, la técnica descrita en PHP.net) es definitivamente desaconsejable. Es simplemente poco fiable.

También resulta problemático llamar a la función mail () desde un método de control de errores. Si tuvieras muchos errores, tu servidor de correo estaría cargado de trabajo y podrías encontrarte con una bandeja de entrada retorcida. Para evitar esto, puede considerar ejecutar un cron para analizar los registros de errores periódicamente y enviar notificaciones en consecuencia. Es posible que también le interese buscar en el software de monitoreo del sistema, como Nagios .

Para hablar con el bit sobre el registro de una función de apagado:

Es cierto que puede registrar una función de apagado, y esa es una buena respuesta.

El punto aquí es que, por lo general, no deberíamos intentar recuperarnos de errores fatales, especialmente si no usamos una expresión regular contra el búfer de salida. Estaba respondiendo a la respuesta aceptada , que estaba vinculada a una sugerencia en php.net que desde entonces ha sido modificada o eliminada.

Esa sugerencia fue utilizar una expresión regular contra el búfer de salida durante el manejo de excepciones, y en el caso de un error fatal (detectado por la coincidencia con cualquier texto de error configurado que pueda estar esperando), intente realizar algún tipo de recuperación o procesamiento continuo. Esa no sería una práctica recomendada (creo que por eso no puedo encontrar la sugerencia original, tampoco. Lo estoy pasando por alto o la comunidad de php lo derribó).

Podría valer la pena señalar que las versiones más recientes de PHP (alrededor de 5.1) parecen llamar a la función de apagado antes, antes de que se produzca la devolución de la llamada del búfer de salida. En la versión 5 y anteriores, ese orden fue el inverso (a la devolución de llamadas del búfer de salida siguió la función de apagado). Además, desde aproximadamente la versión 5.0.5 (que es mucho más antigua que la versión 5.2.3 del interrogador), los objetos se descargan mucho antes de que se llame a una función de apagado registrada, por lo que no podrá confiar en los objetos en memoria para hacerlo. mucho de nada

Por lo tanto, registrar una función de apagado está bien, pero el tipo de tareas que debe realizar una función de apagado probablemente se limitan a unos pocos procedimientos de cierre suave.

La clave para llevar aquí es solo algunas palabras de sabiduría para cualquiera que se tope con esta pregunta y vea el consejo en la respuesta aceptada originalmente. No regex tu buffer de salida.


PHP tiene errores fatales atrapables. Se definen como E_RECOVERABLE_ERROR. El manual de PHP describe un E_RECOVERABLE_ERROR como:

Error fatal detectable. Indica que ocurrió un error probablemente peligroso, pero no dejó el motor en un estado inestable. Si el error no es detectado por un identificador definido por el usuario (consulte también set_error_handler() ), la aplicación se anula porque era un E_ERROR.

Puede "capturar" estos errores "fatales" usando set_error_handler() y verificando E_RECOVERABLE_ERROR. Me parece útil lanzar una excepción cuando se detecta este error, luego puedes usar try / catch.

Esta pregunta y respuesta proporciona un ejemplo útil: ¿Cómo puedo detectar un "error fatal detectable" en las sugerencias de tipo PHP?

Sin embargo, los errores de E_ERROR se pueden manejar, pero no se pueden recuperar ya que el motor está en un estado inestable.


Realmente no. Los errores fatales se llaman así, porque son fatales. No te puedes recuperar de ellos.


Registre errores fatales utilizando register_shutdown_function , que requiere PHP 5.2+:

register_shutdown_function( "fatal_handler" ); function fatal_handler() { $errfile = "unknown file"; $errstr = "shutdown"; $errno = E_CORE_ERROR; $errline = 0; $error = error_get_last(); if( $error !== NULL) { $errno = $error["type"]; $errfile = $error["file"]; $errline = $error["line"]; $errstr = $error["message"]; error_mail(format_error( $errno, $errstr, $errfile, $errline)); } }

Tendrás que definir las funciones error_mail y format_error . Por ejemplo:

function format_error( $errno, $errstr, $errfile, $errline ) { $trace = print_r( debug_backtrace( false ), true ); $content = " <table> <thead><th>Item</th><th>Description</th></thead> <tbody> <tr> <th>Error</th> <td><pre>$errstr</pre></td> </tr> <tr> <th>Errno</th> <td><pre>$errno</pre></td> </tr> <tr> <th>File</th> <td>$errfile</td> </tr> <tr> <th>Line</th> <td>$errline</td> </tr> <tr> <th>Trace</th> <td><pre>$trace</pre></td> </tr> </tbody> </table>"; return $content; }

Use Swift Mailer para escribir la función error_mail .

Ver también:


Se me ocurrió esta solución (PHP 5.2.0+):

function shutDownFunction() { $error = error_get_last(); // fatal error, E_ERROR === 1 if ($error[''type''] === E_ERROR) { //do your stuff } } register_shutdown_function(''shutDownFunction'');

Diferentes tipos de error definidos en http://www.php.net/manual/en/errorfunc.constants.php


Si está usando php> = 5.1.0 Simplemente haga algo como esto con la clase ErrorException:

<?php //define an error handler function exception_error_handler($errno, $errstr, $errfile, $errline ) { throw new ErrorException($errstr, $errno, 0, $errfile, $errline); } //set ur error handle set_error_handler("exception_error_handler"); /* Trigger exception */ try { //try to do something like finding the end of the internet } catch(ErrorException $e) { //anything you want to do with $e } ?>


Solo un buen truco para obtener el método actual error_handler =)

<?php register_shutdown_function(''__fatalHandler''); function __fatalHandler() { $error = error_get_last(); //check if it''s a core/fatal error, otherwise it''s a normal shutdown if($error !== NULL && $error[''type''] === E_ERROR) { //Bit hackish, but the set_exception_handler will return the old handler function fakeHandler() { } $handler = set_exception_handler(''fakeHandler''); restore_exception_handler(); if($handler !== null) { call_user_func($handler, new ErrorException($error[''message''], $error[''type''], 0, $error[''file''], $error[''line''])); } exit; } } ?>

Además, no debería tener en cuenta que si llama

<?php ini_set(''display_errors'', false); ?>

Php deja de mostrar el error; de lo contrario, el texto del error se enviará al cliente antes de su controlador de errores.


Ya que la mayoría de las respuestas aquí son innecesariamente detalladas, aquí está mi versión no fea de la respuesta más votada:

function errorHandler($errno, $errstr, $errfile = '''', $errline = 0, $errcontext = array()) { //Do stuff: mail, log, etc } function fatalHandler() { $error = error_get_last(); if($error) errorHandler($error["type"], $error["message"], $error["file"], $error["line"]); } set_error_handler("errorHandler") register_shutdown_function("fatalHandler");