Wednesday, November 28, 2012


Manejo de Errores en PHP

Los errores son una parte integral de cada lenguaje de programación, aunque los programadores saben esto, la mayoría del tiempo no les gusta lidiar con ellos.

PHP tiene una facilidad excelente para lidiar con errores y provee un excelente nivel de control de cómo los errores son ejecutados, manejados o reportados.

El manejo apropiado de errores consiste en escribir aplicaciones que sean estable, capaces de detectar problemas cuando surgen y de esta forma poder manejar la situación de la mejor manera.

Tipos de errores

Hay diferentes tipos de errores, usualmente son referidos como niveles de errores en PHP:
Errores de compilación Compile-time errors Son errores detectados por el 'parser' de PHP cuando está siendo compilado como un script. No pueden ser 'atrapados' o manejados desde dentro del script.
Errores Fatales Fatal errors Son errores que detienen la ejecución de un script. No se puede 'atrapar' o no puede ser manejado
Errores recuperables Recoverable errors Errores que representan fallos significativos pero que pueden ser manejados de una forma segura. No se puede 'atrapar' o no puede ser manejado
Prevenciones Warnings Son errores que son recuperables e indican un error en el tiempo de ejecución. No detienen la ejecución del script
Notificaciones Notices Indica que un error ocurrió pero no es significativo. No detienen la ejecución del script



Como puedes ver, no siempre se puede detectar una falla o recuperar de ella. Los errores los cuales no puede ser posible recuperarse son los de compilación y los errores fatales pero al menos puede ser advertido que un error pasó durante la ejecución, esto nos da la posibilidad de manejarlo correctamente.

Reporteo de errores (Error Reporting)

Por default, PHP reporta cualquier error que se encuentre en la ejecución del script en el ambiente de 'debugging'. Esto es una característica que no quisieramos tener activada cuando los usuarios esten utilizando nuestra aplicación, debido a que podría significar problemas de seguridad para nuestra aplicación.

Por suerte, hay varias directivas que nos permite pulir cómo los errores son mostrados y esto se puede hacer  en el archivo php.ini. Las más importantes son error_reporting, display_errors and log_errors.

La directiva error_reporting determina cuales errores son reportados por PHP. 

Por ejemplo: error_reporting  = E_ALL & ~E_NOTICE

Tip:  Esta variable puede ser cambiada dinámicamente desde un script ejecutando la función error_reporting()
Ejemplo: error_reporting (E_ERROR); //Sólo mostrará errores y omitirá Notificaciones y Prevenciones (Notice & Warnings)

Las directivas display_errors y log_errors  pueden ser utilizadas para determinar cómo los errores son reportados. Si display_errors es encendida (on), los errores son desplegados en la ejecución del script; generalmente esto no es lo ideal para un ambiente de producción. Bajo estás circunstancias, tendrías que tener encendido log_errors en vez de display_errors para que escriba todos los errores surgidos en el log de errores de tu servidor web

Manejo de Errores

Tu script debe siempre estar capacitado para poder recuperarse de un error incluso si solamente es un aviso de que un error ocurrió y que el usuario posteriormente pueda notificar al departamento de desarrolllo el problema. 

Por suerte el manejo de errores en PHP es sumamente simple. Puedes declarar una función de  'atrapa-todo' que es llamada por PHP cuando surge un error. Esto se puede realizar llamando la siguiente función:

set_error_handler(mifuncion)
donde mifuncion será el nombre de la función que atrapará todo error que surga en la aplicación.

Ejemplo:

function myErrorHandler ($errNo, $errStr, $errFile, $errLine, $errContext) {
         logToFile("Error $errStr in $errFile at line $errLine");
}
set_error_handler (’myErrorHandler’);

Nota: Debe de seguir la siguiente convención para que la función set_error_handler te lo reconozca como una función 'atrapa-todo'.

handler ( int $errno , string $errstr [, string $errfile [, int $errline [, array $errcontext ]]] )

Donde:

errno
El primer parámetro, errno, contiene el nivel del error ocasionado, como un valor de tipo integer.
errstr
El segundo parámetro, errstr, contiene el mensaje de error, como cadena.
errfile
El tercer parámetro es opcional, errfile, que contiene el nombre de archivo que ocasionó el error, como cadena.
errline
El cuarto parámetro es opcional, errline, que contiene el número de línea donde ocurrió el error, como valor de tipo integer.
errcontext
El quinto parámetro es opcional, errcontext, el cuál es una matriz que apunta a la tabla de símbolos activa en el punto donde ocurrió el error. En otras palabras, errcontext contendrá una matriz con cada variable que existe en el ámbito donde el error fue provocado. El gestor de errores de usuario no debe modificar el contexto del error.
Si la función devuelve FALSE se continúa con el gestor de errores normal.

La forma de poder probar esta función es generando una excepción a proposito y se hace de la siguiente forma:

function myErrorHandler ($errNo, $errStr, $errFile, $errLine, $errContext) {
             echo "$errNo, $errStr, $errFile, $errLine"; 
             var_dump ( $errContext ); 
}
set_error_handler (’myErrorHandler’);

trigger_error("Esto es una prueba", E_ERROR);

Aclaro que esta función sólo es de prueba. Dentro de la funcion myErrorHandler ustedes manejarían los errores según sean sus necesidades (ya sea guardandolos en un log, mandando un correo, etc)