error_reporting()
Aprende sobre el reporte de errores en PHP: error_reporting(), display_errors, log_errors y las mejores prácticas para desarrollo y producción.
Introducción
Este capítulo explica cómo PHP reporta errores: la función error_reporting() que controla cuáles errores genera PHP, las directivas display_errors y log_errors que controlan hacia dónde van esos errores, y las funciones auxiliares que se usan para manejarlos y registrarlos. Al finalizar sabrás cómo configurar el reporte de errores de forma diferente para desarrollo y producción, y por qué equivocarse en esto es uno de los errores de seguridad y depuración más comunes en PHP.
Por qué importa el reporte de errores
PHP funciona como un lenguaje dinámicamente tipado y permisivo: muchos errores que detendrían a otro lenguaje durante la compilación se manifiestan en tiempo de ejecución como advertencias, avisos o mensajes de obsolescencia. Si los suprimes, el comportamiento incorrecto puede pasar silenciosamente a producción. Si los muestras a los usuarios finales, puedes filtrar rutas de archivos, SQL y trazas de pila a atacantes.
Un buen reporte de errores logra el equilibrio correcto para cada entorno:
- En desarrollo — muestra todo, de forma visible, para detectar errores mientras los escribes.
- En producción — no muestra nada al usuario, pero registra todo en un archivo para análisis posterior.
Niveles y constantes de error
Los errores de PHP se clasifican por nivel. Cada nivel es una constante predefinida y se combinan con operadores a nivel de bits. Los niveles más comunes:
| Constante | Significado |
|---|---|
E_ERROR | Error fatal en tiempo de ejecución; el script se detiene. |
E_WARNING | Advertencia en tiempo de ejecución; el script continúa. |
E_NOTICE | Aviso (p. ej., usar una variable no definida). |
E_DEPRECATED | Uso de una característica que será eliminada en una versión futura de PHP. |
E_USER_ERROR / E_USER_WARNING / E_USER_NOTICE | Niveles que tú mismo generas con trigger_error(). |
E_ALL | Todos los errores, advertencias y avisos. |
Al ser indicadores de bits, se combinan con | (incluir), & (máscara) y ~ (negar):
// All errors EXCEPT notices and deprecation messages
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
// Only fatal errors and warnings
error_reporting(E_ERROR | E_WARNING);Nota de versión: Desde PHP 8.0 el nivel predeterminado de
error_reportingesE_ALL.E_STRICTfue obsoleto en 8.0 y eliminado en 8.4, y sus avisos ahora se incluyen enE_ALL, por lo que ya no es necesario agregarlo por separado.
Reporte vs. visualización: dos configuraciones distintas
Una fuente frecuente de confusión es que dos interruptores independientes deciden si realmente ves un error:
error_reporting()— decide qué niveles genera PHP.display_errors— decide si los errores generados se imprimen en la salida.
Debes activar ambos para ver un error en pantalla. El siguiente ejemplo genera un aviso de nivel E_ALL y lo imprime porque los dos interruptores están activos:
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
echo $undefined; // Warning: Undefined variable $undefinedSi display_errors estuviera desactivado, el mismo aviso seguiría siendo generado (y podría registrarse) pero no aparecería nada en la salida de la página.
Las funciones principales de reporte de errores
error_reporting()
Establece qué niveles de error se reportan en tiempo de ejecución y devuelve el nivel anterior. Llámala sin argumentos para leer la configuración actual.
<?php
$old = error_reporting(E_ALL & ~E_NOTICE);
echo "Now reporting all errors except notices.\n";
echo "Previous level was: " . $old . "\n";ini_set()
Reemplaza una directiva de php.ini durante la ejecución del script actual. Es el equivalente en tiempo de ejecución de editar php.ini, y es la forma de activar display_errors, display_startup_errors y log_errors desde dentro del código.
<?php
// Development setup: show everything on screen
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);Nota: display_errors no puede capturar errores de análisis fatales en el mismo archivo, porque el archivo completo falla al compilar antes de que se ejecute ini_set(). Para esos casos, configura la directiva directamente en php.ini.
set_error_handler()
Registra un callback que se ejecuta cada vez que se genera un error (no fatal), permitiéndote reemplazar el comportamiento predeterminado de PHP —por ejemplo, para convertir advertencias en excepciones o para darles formato JSON en una API. El callback recibe el nivel, el mensaje, el archivo y la línea del error.
<?php
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
echo "[$errno] $errstr in " . basename($errfile) . " on line $errline\n";
return true; // true = we handled it; PHP's internal handler is skipped
});
echo $undefined; // routed to our handler instead of the default messageConsulta set_error_handler() para ver la firma completa y cómo restaurar el manejador anterior.
error_log() y trigger_error()
error_log()envía un mensaje al log configurado de PHP, a un archivo específico o a una dirección de correo electrónico — nunca a la salida de la página. Esta es la forma segura para producción de registrar problemas.trigger_error()genera un error definido por ti (nivelesE_USER_*), que luego fluye por el mismo pipeline deerror_reporting/manejador que los errores integrados.
<?php
// Append a message to a specific log file (message type 3)
error_log("Payment gateway timed out", 3, "/var/log/php_errors.log");
// Raise a user-level warning that your handler / log can pick up
trigger_error("Cache miss for product 42", E_USER_WARNING);Más información en error_log() y trigger_error().
Configuración recomendada por entorno
En lugar de dispersar la configuración, colócala al principio de tu archivo de arranque.
<?php
// --- Development ---
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');<?php
// --- Production ---
error_reporting(E_ALL); // still GENERATE everything...
ini_set('display_errors', '0'); // ...but never show it to users...
ini_set('log_errors', '1'); // ...log it instead.
ini_set('error_log', '/var/log/php_errors.log');El bloque de producción mantiene visibilidad completa a través de los logs sin exponer nada a los visitantes — la configuración que casi siempre querrás en un servidor en producción.
Buenas prácticas
- Nunca ejecutes producción con
display_errorsactivado. Las rutas filtradas y las trazas de pila son un riesgo de divulgación de información. - Reporta en
E_ALLen todos los entornos. El reporte y la visualización son independientes; suprimir niveles solo oculta errores. - Evita el operador de supresión de errores
@. Oculta errores en el punto de llamada y hace que la depuración sea mucho más difícil; maneja la condición explícitamente en su lugar. - Captura lo que puedas como excepciones. Para fallos recuperables, prefiere
try/catchsobre los manejadores de error. Consulta PHP Exceptions. - Usa una biblioteca de logging en aplicaciones grandes. Herramientas como Monolog te ofrecen niveles de log, rotación y múltiples destinos sobre
error_log().
Conclusión
El reporte de errores en PHP se resume en tres capas: elegir los niveles con error_reporting(), elegir el destino con display_errors / log_errors, y opcionalmente personalizar el manejo con set_error_handler() y trigger_error(). Configúralos de forma deliberada — verboso en pantalla durante el desarrollo, silencioso pero registrado en producción — y obtendrás una depuración rápida sin exponer tu aplicación a los usuarios ni a los atacantes.
Lectura relacionada: PHP Error handling · error_get_last() · try…catch.