Gestión de Errores en PHP
Ya casi dos años sin Internet en casa me ha hecho controlar un poco esa horrible costumbre de chatear casi todo el día y cambiarla por programar alguna tontería (Re-Inventar la rueda obviamente puff! :P ).
Esta vez estuve pensando como solucionar el problema al que me enfrento cuando estoy a cargo de varios proyectos al mismo tiempo, y me veo en la situación de trabajar casi a ciegas, y sin revisar la entrada de datos detenidamente, o sencillamente si funciona o no… y todo debido a la presión del trabajo.
La idea es encontrar todos los errores de forma rápida, sencilla, y sin tener que navegar o testear mis aplicaciones Web una y otra vez cada que hago modificaciones o nuevas implementaciones.
Se me ocurrió que existiera la posibilidad de anular el gestor de errores de PHP, y crear un propio que me permitiera guardar los errores en un archivo, y luego de cierto tiempo revisarlo y que ahí estuviera cacheados todos los errores ocurridos… Y bueno, después de leer un rato la documentación de PHP terminé configurando el servidor a mi medida desde el php.ini, pero,… pensé ¿Se podrá crear una función aplicable a cada sistema en particular sin revolver todos los errores de todos los sistemas en el mismo log de errores? Bueno, la respuesta fue si, y no solo eso, me encontré con que las posibilidades son mayores: Puedo de cierta forma cachear el contexto en el que el error ha ocurrido, por ejemplo guardar todas las variables en GET y POST. Esto me ayudaría a darme cuenta de si alguien mal intencionado insertó alguna consulta que me halla causado el error (la IP, los datos de sesión de algún usuario, etc…).Y bueno, he aquí los resultados:
- define('error_file','error_log.html');
- function error_handler($num_err, $cadena_err, $archivo_err="", $linea_err="", $contexto_err=""){
- /*
- (PHP 4 >= 4.0.1, PHP 5)
- $num_err - nivel de error generado, como un entero.
- $cadena_err - mensaje de error, como una cadena.
- PHP >= 4.0.2
- $archivo_err - nombre del archivo en el que se generó el error, como una cadena.
- $linea_err - número de lÃnea en la que se generó el error, como un entero.
- $contexto_err - matriz que apunta a la tabla activa de sÃmbolos en el punto en el que ocurrio el error.
- */
- $errores = array (
- E_ERROR => 'E_ERROR',
- E_WARNING => 'E_WARNING',
- E_PARSE => 'E_PARSE',
- E_NOTICE => 'E_NOTICE',
- E_CORE_ERROR => 'E_CORE_ERROR',
- E_CORE_WARNING => 'E_CORE_WARNING',
- E_COMPILE_ERROR => 'E_COMPILE_ERROR',
- E_COMPILE_WARNING => 'E_COMPILE_WARNING',
- E_USER_ERROR => 'E_USER_ERROR',
- E_USER_WARNING => 'E_USER_WARNING',
- E_USER_NOTICE => 'E_USER_NOTICE'
- );
- if(defined('E_STRICT'))
- $errores[E_STRICT] = 'E_STRICT';// PHP > 5
- if(defined('E_RECOVERABLE_ERROR'))
- $errores[E_RECOVERABLE_ERRROR] = 'E_RECOVERABLE_ERRROR';// PHP > 5.2
- ob_start();
- echo "<strong>{$errores[$num_err]}</strong>: $cadena_err in <strong>$archivo_err</strong> on line <strong>$linea_err</strong>";
- //echo date(" Y-m-d H:i:s (T)");
- //PHP >= 4.0.2, para versiones anteriores habrÃa que analizar si _GET o _POST están definidos y tienen valores
- /*Si el contexto en el que ocurrieron los errores venÃa acompañado de variables
- por el método _POST, estas se mostrarán en el error.*/
- if(isset($contexto_err['_POST']) and count($contexto_err['_POST'])>0){
- echo " _POST: ";
- echo"<pre>";
- print_r($contexto_err['_POST']);
- echo"</pre>";
- }
- /* Lo mismo para _GET */
- if(isset($contexto_err['_GET']) and count($contexto_err['_GET'])>0){
- echo"<pre>";
- echo"_GET:";
- print_r($contexto_err['_GET']);
- echo"</pre>";
- }
- echo "<br />n";
- error_log(ob_get_clean(), 3, error_file);
- }
Para utilizarla, solo hay que incluir la función en la aplicación, y decirle a php que la convierta en el manejador de errores de la siguiente forma:
- set_error_handler("error_handler");
donde error_handler corresponde al nombre de la función que recibirá todos los datos correspondientes a los errores, para que hagamos lo que queramos con ellos.
Y para las consultas SQL no encontré una forma de hacerlo similar a la anterior, pero si se me ocurrió hacerlo algo así como con el clásico or die(mysql_error) de la siguiente forma:
- define('error_file','error_log.html');
- function guardar_error($linea){
- $fh = fopen(error_file,"a");
- fwrite($fh,"<strong>Mysql_error ".mysql_errno()."</strong>: ".mysql_error()." in <strong>{$_SERVER['SCRIPT_FILENAME']}</strong> on line <strong>$linea</strong><br />n");
- }
- Mysql_query($sqlStr) or die(guardar_error(__LINE__));
Y de igual forma, ir controlando un poco los errores.
No tengo idea de si he re-inventado la rueda, o exista una solución parecida a la mia y mejor aún, pero… Me sacó del apuro en el trabajo :D
Cualquier duda, comentario, sugerencia, desacuerdo o mentada es bien recibida. ;-)
j0an
2006-12-13 16:44:18
gracias! ya lo tengo a prueba a ver como funciona y si me termina sirviendo (administro cerca de 10 sitios, y me viene barbaro)
:)
Victor
2006-12-13 16:49:51
:-D Suerte con eso, cualquier detalle, por aquí puedes comentarle :-)
Manejo errores con php
2007-05-28 06:04:15
[...] Gestión de Errores en PHP [...]
tttony
2007-07-25 01:19:03
hola estaba buscando algo similar a esto pero veo no solo se guarda el error en el caso de mysql y no se podria mostrar algo al usuario como: ha ocurrido un error inesperado....
y bueno tambien para el otro caso si algun usuario como siempre pasa cambia un valor GET o POST deberia de mostrar un mensaje de error personalizado...
saludos y espero respuestas...