Toda guía sobre un problema de PHP empieza con «active display_errors». En un sitio en producción eso imprime sus rutas de archivo, su framework y a veces el nombre de su base de datos a cualquiera capaz de hacer fallar la página, incluido quien lo está intentando.

Los ajustes correctos para producción

display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/mysite-error.log
error_reporting = E_ALL & ~E_DEPRECATED

E_ALL sin las obsolescencias mantiene el registro legible en un código antiguo y sigue anotando todo lo que de verdad está mal.

Mírelo mientras reproduce el fallo

tail -f /var/log/php/mysite-error.log

Deje eso corriendo y cargue la página rota. Obtiene la misma información que habría mostrado display_errors, en el mismo instante, sin que ningún visitante llegue a verla.

Si de verdad necesita verlo en el navegador

Enséñeselo solo a usted, por dirección:

if ((@$_SERVER["REMOTE_ADDR"] ?? "") === "YOUR.IP.HERE") {
    ini_set("display_errors", "1");
    error_reporting(E_ALL);
}
Ponga eso tras una comprobación que no pueda olvidarse de quitar: una constante en un archivo de configuración que no se despliega, no una línea comentada. Una línea comentada acaba descomentándose.

Un registro que crece demasiado deprisa

sort /var/log/php/mysite-error.log | uniq -c | sort -rn | head -5

Un aviso en cada petición escribe gigabytes en un día. La primera línea de esa salida es casi siempre todo el problema.

Vuelva a activar las obsolescencias un día antes de subir de versión de PHP. Son los avisos que se convierten en errores en la siguiente versión, y leerlos pronto es la preparación más barata que existe.