Cómo capturar y mostrar los errores en PHP, parámetros de configuración para errores, constantes

En muchas situaciones, sobre todo en desarrollo y depuración, necesitamos saber qué errores se están produciendo y en qué momento en nuestros desarrollos PHP. También puede ser útil mostrar el error a los usuarios finales, pero sólo en determinadas circunstancias. Os mostramos en este artículo cómo capturar y mostrar los errores en el navegador cuando usamos PHP como lenguaje de programación web.

Requisitos y configuración previa para el manejo de errores en PHP

En cuanto a requisitos, no es necesario establecer ninguno, el núcleo de PHP ya cuenta con las funciones, procedimientos y constantes para el manejo de errores.

El manejo de errores en PHP ha ido cambiando desde sus primeras versiones hasta la fecha, sobre todo enfocando los cambios a la seguridad. En las versiones actuales (7.1.9) está muy controlado y, por defecto, no se muestran errores al usuario final en su navegador. Esto es así por seguridad, algunos errores pueden comprometer seriamente la seguridad de nuestro sitio web, al mostrar informción interna del servidor, o de la base de datos y sus tablas.

Por lo tanto, para las versiones actuales de PHP, existen varios parámetros de configuración que se establecen en el fichero php.ini (fichero de configuración de PHP):

Opciones de configuración de errores y registro
Nombre Por defecto Uso, descripción Versión PHP
error_reporting NULL Establece el nivel de notificación de errores. El parámetro es o bien un valor de tipo integer que representa un campo de bits, o bien constantes con nombre.
display_errors “1” Determina si los errores deberían ser impresos en pantalla como parte de la salida o si deberían ocultarse al usuario.
display_startup_errors “0” Incluso cuando display_errors está activado, los errores que ocurren durante la secuencia de arranque de PHP no se muestran. Se recomienda encarecidamente mantener desactivado display_startup_errors, excepto para la depuración.
log_errors “0” Indica si los mensajes de error del script deberían de registrarse en el registro del servidor o en error_log. Esta opción es, por lo tanto, específica para servidores.
log_errors_max_len “1024” Establece la longitud máxima de log_errors en bytes. En error_log se añade información acerca del origen. El valor predeterminado es 1024 y permite no aplicar ninguna longitud máxima en absoluto. Esta longitud se aplica a los errores registrados, a los errores mostrados y también a $php_errormsg, pero no a las funciones llamadas explícitamente tal como error_log(). Disponible a partir de PHP 4.3.0.
ignore_repeated_errors “0” No registra mensajes repetidos. Los mensajes repetidos deben ocurrir en la misma línea del mismo fichero a menos que ignore_repeated_source esté establecido a true. Disponible a partir de PHP 4.3.0.
ignore_repeated_source “0”

Ignora el origen del mensaje cuando se ignoran mensajes repetidos. Cuando este ajuste está activado (On) no se registrarán errores con mensajes repetidos de diferentes ficheros o líneas del código fuente.

Disponible a partir de PHP 4.3.0.
report_memleaks “1” Si este parámetro está activado (On), que es lo predeterminado, mostrará un informe de pérdidas de memoria detectado por el gestor de memoria Zend. Este informe será enviado a stderr en las plataformas Posix. En Windows, será enviado al depurador usando OutputDebugString(), y podrá ser visto con herramientas como DbgView. Este parámetro solo tiene efecto en una versión de depuración, y si error_reporting incluye E_WARNING en la lista permitida. Disponible a partir de PHP 4.3.0.
track_errors “0” Si está habilitado, el último mensaje de error siempre estará presente en la variable $php_errormsg.
html_errors “1” Desactiva las etiquetas HTML en los mensajes de error. El nuevo formato para errores HTML producen mensajes clicables que dirigen al usuario a una página describiendo el error o a la función que causa el error. Estas referencias se ven afectadas por docref_root y docref_ext. PHP_INI_SYSTEM en PHP <= 4.2.3.
xmlrpc_errors “0”

Desactiva la notificación de errores normales y formatea los errores como mensajes de error XML-RPC.

Disponible a partir de PHP 4.1.0.
xmlrpc_error_number “0”

Usado como el valor del elemento faultCode de XML-RPC.

Disponible a partir de PHP 4.1.0.
docref_root “” El nuevo formato de error contiene una referencia a una página que describe el error o a la función que causa el error. En caso de páginas de manual, se puede descargar el manual en su idioma y establecer esta directiva ini al URL de su copia local. Si a su copia local del manual se puede llegar mediante “/manual/” puede usar simplemente docref_root=/manual/. Además tiene que establecer docref_ext para que coincida con las extensiones de fichero de su copia docref_ext=.html. Es posible usar referencias externas. Disponible a partir de PHP 4.3.0.
docref_ext “” Véase docref_root. Disponible a partir de PHP 4.3.2.
error_prepend_string NULL

String a imprimir antes de un mensaje de error.

error_append_string NULL

String a imprimir después de un mensaje de error.

error_log NULL Nombre del fichero donde los errores del script deberían ser registrados. El fichero debería ser modificable por el usuario del servidor web. Si se usa el valor especial syslog, los errores son enviados en su lugar al registro del sistema. En Unix, esto quiere decir syslog(3) y en Windows NT quiere decir el registro de sucesos. El registro de sistema no está admitido en Windows 95. Si esta directiva no está establecida, los errores se enviarán al registro de error de la SAPI. Por ejemplo, un registro de error en Apache o stderr en CLI.

 

PHP cuenta con una serie de constantes donde almacena determinados valores para la gestión de los errores:

 Valor Nombre y descripción
1 E_ERROR (integer) Errores fatales en tiempo de ejecución. Éstos indican errores que no se pueden recuperar, tales como un problema de asignación de memoria. La ejecución del script se interrumpe.
2 E_WARNING (integer) Advertencias en tiempo de ejecución (errores no fatales). La ejecución del script no se interrumpe.
4 E_PARSE (integer) Errores de análisis en tiempo de compilación. Los errores de análisis deberían ser generados únicamente por el analizador.
8 E_NOTICE (integer) Avisos en tiempo de ejecución. Indican que el script encontró algo que podría señalar un error, pero que también podría ocurrir en el curso normal al ejecutar un script.
16 E_CORE_ERROR (integer) Errores fatales que ocurren durante el arranque incial de PHP. Son como un E_ERROR, excepto que son generados por el núcleo de PHP.
32 E_CORE_WARNING (integer) Advertencias (errores no fatales) que ocurren durante el arranque inicial de PHP. Son como un E_WARNING, excepto que son generados por el núcleo de PHP.
64 E_COMPILE_ERROR (integer) Errores fatales en tiempo de compilación. Son como un E_ERROR, excepto que son generados por Motor de Script Zend.
128 E_COMPILE_WARNING (integer) Advertencias en tiempo de compilación (errores no fatales). Son como un E_WARNING, excepto que son generados por Motor de Script Zend.
256 E_USER_ERROR (integer) Mensaje de error generado por el usuario. Es como un E_ERROR, excepto que es generado por código de PHP mediante el uso de la función de PHP trigger_error().
512 E_USER_WARNING (integer) Mensaje de advertencia generado por el usuario. Es como un E_WARNING, excepto que es generado por código de PHP mediante el uso de la función de PHP trigger_error().
1024 E_USER_NOTICE (integer) Mensaje de aviso generado por el usuario. Es como un E_NOTICE, excepto que es generado por código de PHP mediante el uso de la función de PHP trigger_error().
2048 E_STRICT (integer) Habilítelo para que PHP sugiera cambios en su código, lo que asegurará la mejor interoperabilidad y compatibilidad con versiones posteriores de PHP de su código. Desde PHP 5 pero no incluidoen E_ALL hasta PHP 5.4.0
4096 E_RECOVERABLE_ERROR (integer) Error fatal capturable. Indica que ocurrió un error probablemente peligroso, pero no dejó al Motor en un estado inestable. Si no se captura el error mediante un gestor definido por el usuario, la aplicación se abortará como si fuera un E_ERROR. Desde PHP 5.2.0
8192 E_DEPRECATED (integer) Avisos en tiempo de ejecución. Habilítelo para recibir avisos sobre código que no funcionará en futuras versiones. Desde PHP 5.3.0
16384 E_USER_DEPRECATED (integer) Mensajes de advertencia generados por el usuario. Son como un E_DEPRECATED, excepto que es generado por código de PHP mediante el uso de la función de PHP trigger_error(). Desde PHP 5.3.0
32767 E_ALL (integer) Todos los errores y advertencias soportados, excepto del nivel E_STRICT antes de PHP 5.4.0. 32767 en PHP 5.4.x, 30719 en PHP 5.3.x, 6143 en PHP 5.2.x, 2047 anteriormente

 

Funciones de manejo de errores genéricas en PHP

PHP cuenta con una serie de funciones para el manejo de errores, destinadas al uso por los desarrolladores, para elegir en qué momento y circunstancias mostrar errores de ejecución.

A continuación mostramos una tabla con estas funciones y su uso:

Función Uso
debug_backtrace Genera un rastreo
debug_print_backtrace Muestra un rastreo PHP, uestra las llamadas a función, archivos incluídos y el material evaluado mediante eval().
 error_clear_last  Limpia los errores más recientes, no pudiéndose recuperarlos así con error_get_last().
 error_get_last  Devuelve el último error que ocurrió. Devuelve una matriz asociativa describiendo el último error con las claves “type” (tipo), “message” (mensaje), “file” (archivo) y “line” (línea). Si el error ha sido causado por una función interna de PHP, el “message” (mensaje) comienza con su nombre. Devuelve NULL si no ha habido aún un error.
 error_log

Enviar un mensaje de error a las rutinas de manejo de errores definidas. Envía un mensaje de error al registro de errores del servidor web o a un fichero.

 error_reporting  Establece qué errores de PHP son notificados.  La función error_reporting() establece la directiva error_reporting en tiempo de ejecución. PHP tiene varios niveles de errores para notificar, al utilizar ésta función se define el nivel de duración (tiempo de ejecución) de sus scripts. Si el parámetro opcional level no se define, la función error_reporting() sólo devolverá el nivel actual de notificación de error. 
 restore_error_handler  Recupera la función de gestión de errores previa. Usada después de modificar la función de gestión de errores usando set_error_handler(), para revertir al gestor de errores previo (el cual puede ser el incorporado o una función definida por el usuario).
 restore_exception_handler  Restaura la función de gestión de excepciones previamente definida. Usada después de cambiar la función de gestión de excepciones al utilizar set_exception_handler(), para volver al gestor de excepciones anterior (el cuál puede ser la función interna o una definida por el usuario).
 set_error_handler  Establecer una función de gestión de errores definida por el usuario. Establece una función de usuario (error_handler) para manejar los errores de un script.
 set_exception_handler  Establece una función de gestión de excepciones definida por el usuario. Establece el manejador de excepciones predeterminado si una excepción no es capturada dentro de un bloque try/catch. La ejecución se detendrá después de la llamada a exception_handler.
 trigger_error Generar un mensaje de error/advertencia/aviso de nivel de usuario. Se usa para provocar una condición de error de usuario, se puede utilizar junto con el gestor de errores interno o con una función definida por el usuario que ha sido establecida como el nuevo gestor de errores (set_error_handler()). Esta función es útil cuando se necesita generar una respuesta en particular a una excepción en tiempo de ejecución.
 user_error  Esta función es un alias de: trigger_error().

 

Por supuesto, PHP puede contar con otras muchas funciones de manejo de errores específicas, por ejemplo:

Función Uso
mysqli_errno Devuelve el código del error de la última función llamada. Devuelve el último código de error de la llamada más reciente a una función MySQLi que podrá haberse ejecutado con éxito o haber fallado.
 mysqli_error  Devuelve una cadena que describe el último error MySQL. Devuelve el últmo mensaje de error para la llamada más reciente a una función de MySQLi que puede haberse ejecutado correctamente o haber fallado. 
 mysql_errno  [OBSOLETA] Devuelve el valor numérico del mensaje de error de la última operación MySQL. Esta extensión fue declarada obsoleta en PHP 5.5.0 y eliminada en PHP 7.0.0. En su lugar debería utilzarse las extensiones MySQLi o PDO_MySQL.
 mysql_error [OBSOLETA] Devuelve el texto del mensaje de error de la operación MySQL anterior. Esta extensión fue declarada obsoleta en PHP 5.5.0 y eliminada en PHP 7.0.0. En su lugar debería utilzarse las extensiones MySQLi o PDO_MySQL.
 mysqli_connect_error  Devuelve una cadena con la descripción del último error de conexión. Devuelve el último mensaje de error de la ultima llamada mysqli_connect().
mysqli_connect_errno Devuelve el código de error de la última llamada. Devuelve el ultimo código de error de la última llamada mysqli_connect().

Ejemplo de captura de posible error en PHP mediante try…catch o finally

PHP cuenta con el método de captura de excepciones potenciales usando try…catch…finally a partir de su versión 5.0, de forma que se puede añadir esta estructura a cualquier parte de nuestro código PHP susceptible de generar algún error. Conseguiremos poder capturar la excepción y decidir si mostrar aviso al usuario o no (silenciosa).

Mediante try…catch…finally podemos obtener el tipo de excepción y proceder en consecuencia. A continuación mostramos un ejemplo sencillo de captura de un posible error o excepción en una parte de nuestro código PHP:

A ejecutar el código anterior mostrará el resultado:

Error en división por cero.
Seguirá la ejecución del programa.

Aunque hay que tener en cuenta que, en función de la configuración de PHP (php.ini) y la versión de PHP, puede que el comportamiento ante la captura de error difiera entre unos servidores y otros.

Como vemos en el código, el tratamiento de errores en PHP, en ocasiones, puede ser un poco “engorroso”. Esto es así porque el tratamiento de errores depende de la versión de PHP con la que estemos trabajando. En el ejemplo anterior no hay una forma de capturar el error de división por cero de forma específica, el usuario recibiría el mensaje “Error en división por cero” tanto si se trata de un error de división por cero como de cualquier otro tipo de error.

A partir de PHP 7 se ha añadido la captura de errores por tipo, lo cual facilita la gestión a la hora de mostrar mensajes al usuario o de realizar determinadas tareas. Por ejemplo, en el caso anterior, para PHP 7 podría definirse el siguiente tratamiento de errores:

Como vemos, en este caso sí que hay un tratamiento específico para el caso de división por cero (DivisionByZeroError), pero necesitaremos disponer de PHP 7 en nuestro servidor web. Si ejecutamos este código en servidores con versión inferior a PHP 7 obtendremos un mensaje como el siguiente:

Warning: Division by zero in …\htdocs\error_cero.php on line 30

Si queremos que, tanto si se produce un error como si no, se ejecute un determinado código podremos usar finally. Por ejemplo:

 

Mostrar último mensaje de error en operaciones con MySQL y MariaDB desde PHP

En determinados casos puede que queramos capturar y mostrar los posibles errores que se produzcan al ejecutar acciones sobre una base de datos MySQL o MariaDB. En el caso de PHP, cuenta con algunas funciones para mostrar errores que se puedan producir.

Por ejemplo, supongamos el siguiente código PHP con eliminación de un registro de una tabla de la base de datos:

En el ejemplo anterior eliminamos un registro de la base de datos, si el SQL se ejecuta correctamente mostraríamos un mensaje: Registro eliminado correctamente y si ha habido algún error mostraríamos el mensaje: Error al eliminar el registro.

Si queremos ser más específicos y mostrar el código del error y la descripción podemos usar mysqli_errno() y mysqli_error(), siempre que la conexión a la base de datos MySQL o MariaDB la hayamos establecido con mysqli_connect. El código anterior quedaría de la siguiente manera:

De esta forma nuestra aplicación web en PHP mostraría, en caso de producirse un error, el número del error y la descripción:

Como hemos comentado al principio, hay que decidir en cada caso si es conveniente (sobre todo por seguridad) mostrar o no la información detallada de los errores. Esto es elección del desarrollador y debe ser meticuloso al respecto. Cuando estamos depurando y desarrollando una aplicación este “truco” nos vendrá de maravilla para ir viendo los posibles errores que se puedan producir. Pero cuando la aplicación está en producción tal vez no sea conveniente.

Mostrar información de error de este tipo:

Error al eliminar el registro: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘@ddDPZ_ffD, codigo))=fc2387da5940377fa037db069526d59a’ at line 1

Es poco seguro, estamos informando al usuario sobre el motor de base de datos que usamos (MySQL), y sobre otras muchas cosas.

Lo mismo ocurre con la conexión al servidor de base de datos MySQL desde PHP, podemos capturar un posible error de conexión con mysqli_connect_errno() y mysqli_connect_error():

 

Conclusión, tratamiento de errores PHP

A partir de PHP 7 el tratamiento de errores está muy optimizado y mejorado, incluso se pueden gestionar los errores como clases (Programación Orientada a Objetos).

Hasta PHP 4 el tratamiento de errores dejaba bastante que desear, a partir de PHP 5 introdujeron algunas mejoras como el try…catch…finally.

Así pues el problema principal del tratamiento de errores en PHP es que es muy variable en función de la versión usada. Si tenemos una aplicación “grande” desarrollada ya en PHP 4, por ejemplo, será bastante costoso actualizarla y compatibilizarla con PHP 7 en cuanto al tratamiento de errores se refiere. Por ello muchos desarrolladores optan por deshabilitar la opción de mostrar los errores desde php.ini y hacer su propio tratamiento de errores interno.

Lo explicado en este artículo es el mínimo para tratamiento de errores, hay muchísimas más posibilidades. Hemos tratado de explicar lo básico, al menos.

alonsojpd

alonsojpd

Presidente y fundador de Proyecto A y AjpdSoft

También te podría gustar...

2 Respuestas

Deja un comentario