
Trabajo con Logs en PHP
Cuando desarrollamos una aplicación se suceden numerosos flujos de ejecución, peticiones y respuesta, reactividad, etc. y todos son posibles contextos donde se puede ubicar un error, por poner un ejemplo, en una aplicación básica de compra, pueden darse errores en el registro, en las peticiones a la base de datos a la hora de validar un login, al añadir un ítem al carro…
Podemos utilizar los logs (registros) como una forma de controlar esos pequeños flujos dentro del sistema, derivando a un fichero de texto la información relevante.
Tanto el trabajo directo con archivos como el uso de ini_set
son métodos para gestionar registros (logs) en PHP, pero tienen diferencias clave en su implementación y uso:
Trabajo directo con archivos:
- Control completo: Cuando trabajas directamente con archivos, tienes un control completo sobre cómo se gestionan los registros. Puedes personalizar el formato, el contenido y la estructura de los registros según tus necesidades específicas.
- Flexibilidad: Puedes decidir dónde y cómo se almacenan los registros. Esto te permite guardar registros en diferentes archivos, en diferentes formatos o incluso enviarlos a ubicaciones remotas si es necesario.
- Requiere más código personalizado: Trabajar con archivos directamente generalmente implica escribir más código personalizado para abrir, escribir y cerrar archivos. Esto puede ser beneficioso si necesitas un alto grado de personalización y control.
- Posible sobrecarga de recursos: Si se utilizan en exceso, las operaciones de escritura de archivos pueden consumir recursos, especialmente si se accede a los registros con frecuencia. Esto puede afectar el rendimiento de la aplicación.
Un ejemplo de implementación:
<?php
// Mensaje que deseas registrar en el archivo de logs
$logMessage = "Se ha accedido al archivo index.php el " . date("Y-m-d H:i:s") . "\n";
// Ruta al archivo de logs
$logFile = "logs.txt";
// Abre el archivo de logs en modo de escritura (si no existe, se crea)
if ($file = fopen($logFile, "a")) {
// Escribe el mensaje en el archivo de logs
fwrite($file, $logMessage);
// Cierra el archivo
fclose($file);
} else {
// Manejo de errores si no se puede abrir el archivo
echo "No se pudo abrir el archivo de logs.";
}
// Resto de tu código de la aplicación
?>
<!DOCTYPE html>
<html>
<head>
<title>Mi Página Web</title>
</head>
<body>
<h1>Bienvenido a mi página web</h1>
<!-- El contenido de tu página web -->
</body>
</html>
Uso de ini_set con error_log:
- Configuración global:
ini_set
te permite cambiar la configuración de PHP de manera global, incluida la configuración relacionada con registros de errores. En particular, puedes usarini_set
para especificar la ubicación del archivo de registro y otros parámetros de registro de errores. - Facilidad de uso: Configurar registros con
ini_set
es más simple y menos propenso a errores en comparación con la gestión manual de archivos. Es una forma rápida de redirigir mensajes de error a un archivo de registro sin tener que escribir mucho código adicional. - Menos control personalizado: Aunque puedes configurar la ubicación del archivo de registro y algunos parámetros básicos, tienes menos control sobre el formato y el contenido de los registros. Los registros generados con
error_log
suelen tener un formato predefinido y pueden ser menos flexibles en ese aspecto. - Más limitado para aplicaciones complejas: Para aplicaciones que requieren una lógica de registro personalizada o múltiples archivos de registro, trabajar directamente con archivos puede ser más adecuado que el enfoque de
ini_set
.
Ejemplo de implementación usando ini_set:
<?php
// Ruta al archivo de registro de errores
$logFile = 'logs.txt';
// Configura PHP para redirigir mensajes de error al archivo de registro
ini_set('log_errors', 1);
ini_set('error_log', $logFile);
// Mensaje de error personalizado
$errorMessage = 'Ha ocurrido un error inesperado en la aplicación.';
// Intenta ejecutar una operación que podría generar un error
$result = dividePorCero(10, 0);
// Verifica si $result contiene un valor booleano falso, lo que indica un error
if ($result === false) {
// Obtiene información sobre el error actual
$errorInfo = error_get_last();
// Verifica si hay un error y si es un error de tipo E_ERROR
if ($errorInfo !== null && $errorInfo['type'] === E_ERROR) {
// Registra el mensaje de error en el archivo de registro
error_log($errorMessage);
// También puedes imprimir el mensaje de error en el navegador o realizar otras acciones
echo $errorMessage;
}
}
// Función personalizada que puede generar un error
function dividePorCero($numerator, $denominator) {
if ($denominator === 0) {
// Intentar dividir por cero generará un error
return false;
} else {
return $numerator / $denominator;
}
}
?>
En ambos casos la salida será similar, un registro que almacenará la información que hemos enviado en base al flujo de ejecución del sistema, un ejemplo:
[02-Sep-2023 19:58:43 Europe/Berlin] Error al ejecutar la función 'guardar' para el objeto Pueblo: Error en la ejecución de la consulta SQL: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
[02-Sep-2023 19:58:43 Europe/Berlin] Archivo: C:\xampp\htdocs\Galoria-master\modelos\Pueblo.php
[02-Sep-2023 19:58:43 Europe/Berlin] Línea: 72
[02-Sep-2023 19:58:43 Europe/Berlin] Trace: #0 C:\xampp\htdocs\Galoria-master\controladores\Registro.php(38): Pueblo->guardar()
#1 {main}
[02-Sep-2023 20:04:17 Europe/Berlin] Se ha registrado el usuario: Coque con ID:
[02-Sep-2023 20:04:17 Europe/Berlin] ID del jugador: 47
[02-Sep-2023 20:04:17 Europe/Berlin] Nombre del pueblo: Pueblo 69
[02-Sep-2023 20:04:17 Europe/Berlin] Espacios de edificios: , , , , , , , , , , ,
[02-Sep-2023 20:04:17 Europe/Berlin] La consulta se ejecutó con éxito.
[04-Sep-2023 20:59:54 Europe/Berlin] Se ha registrado el usuario: Usuario1 con ID:
[04-Sep-2023 20:59:54 Europe/Berlin] ID del jugador: 48
[04-Sep-2023 20:59:54 Europe/Berlin] Nombre del pueblo: Pueblo 734
[04-Sep-2023 20:59:54 Europe/Berlin] Espacios de edificios: , , , , , , , , , , ,
[04-Sep-2023 20:59:54 Europe/Berlin] La consulta se ejecutó con éxito.
[04-Sep-2023 21:42:25 Europe/Berlin] Se ha registrado el usuario: usuarioTest con ID:
[04-Sep-2023 21:42:25 Europe/Berlin] ID del jugador: 49
[04-Sep-2023 21:42:25 Europe/Berlin] Nombre del pueblo: Pueblo 116
[04-Sep-2023 21:42:25 Europe/Berlin] Espacios de edificios: , , , , , , , , , , ,
[04-Sep-2023 21:42:25 Europe/Berlin] La consulta se ejecutó con éxito.
[04-Sep-2023 21:42:54 Europe/Berlin] Se ha registrado el usuario: unpaisano con ID:
[04-Sep-2023 21:42:54 Europe/Berlin] ID del jugador: 50
[04-Sep-2023 21:42:54 Europe/Berlin] Nombre del pueblo: Pueblo 68
[04-Sep-2023 21:42:54 Europe/Berlin] Espacios de edificios: , , , , , , , , , , ,
[04-Sep-2023 21:42:54 Europe/Berlin] La consulta se ejecutó con éxito.
[04-Sep-2023 21:43:31 Europe/Berlin] Se ha registrado el usuario: Archivito con ID:
[04-Sep-2023 21:43:31 Europe/Berlin] ID del jugador: 51
[04-Sep-2023 21:43:31 Europe/Berlin] Nombre del pueblo: Pueblo 108
[04-Sep-2023 21:43:31 Europe/Berlin] Espacios de edificios: , , , , , , , , , , ,
[04-Sep-2023 21:43:31 Europe/Berlin] La consulta se ejecutó con éxito.
[05-Sep-2023 11:13:21 Europe/Berlin] Se ha registrado el usuario: usuario2 con ID:
[05-Sep-2023 11:13:21 Europe/Berlin] ID del jugador: 52
[05-Sep-2023 11:13:21 Europe/Berlin] Nombre del pueblo: Pueblo 37
[05-Sep-2023 11:13:21 Europe/Berlin] Espacios de edificios: , , , , , , , , , , ,
[05-Sep-2023 11:13:21 Europe/Berlin] La consulta se ejecutó con éxito.
[05-Sep-2023 11:17:04 Europe/Berlin] Se ha registrado el usuario: martin con ID:
[05-Sep-2023 11:17:04 Europe/Berlin] ID del jugador: 53
[05-Sep-2023 11:17:04 Europe/Berlin] Nombre del pueblo: Pueblo 34
[05-Sep-2023 11:17:04 Europe/Berlin] Espacios de edificios: , , , , , , , , , , ,
[05-Sep-2023 11:17:04 Europe/Berlin] La consulta se ejecutó con éxito.
En este fragmento de logs, perteneciente a un sistema de registro de usuarios, podemos ver la utilidad de estos sistemas, primero por permitir llevar un control de registro y segundo, por como se ve en las primeras líneas, exponer errores.
En resumen, la elección entre trabajar directamente con archivos y usar ini_set
depende de tus necesidades específicas. Si deseas un control completo y flexibilidad en la gestión de registros, trabajar directamente con archivos es la mejor opción. Por otro lado, si deseas una solución rápida y sencilla para redirigir mensajes de error a un archivo de registro, ini_set
puede ser más conveniente, ambas opciones son muy eficientes en líneas generales.
En el manual de logs de PHP encontrarás esta información de manera más práctica: logs en PHP.