Files
f3-simple-blog/app/Helpers/Error.php
2026-03-27 22:30:10 +01:00

88 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
function app_bootstrap_logging(): void
{
$dir = rtrim((string) Base::instance()->get('LOGS'), '/\\') . DIRECTORY_SEPARATOR;
app_ensure_dir($dir);
ini_set('log_errors', '1');
ini_set('error_log', $dir . 'php-error.log');
ini_set('display_errors', app_is_prod() ? '0' : '1');
error_reporting(E_ALL);
}
function app_error_meta(int $code): array
{
return match ($code) {
400 => ['title' => 'Requête invalide', 'message' => 'La requête envoyée est invalide.'],
403 => ['title' => 'Accès refusé', 'message' => 'Tu n\u2019as pas accès à cette ressource.'],
404 => ['title' => 'Page introuvable', 'message' => 'La page demandée est introuvable.'],
default => ['title' => 'Erreur serveur', 'message' => 'Une erreur est survenue.'],
};
}
function app_render_error_fallback(int $code): void
{
$meta = app_error_meta($code);
$base = rtrim((string) Base::instance()->get('BASE'), '/');
while (ob_get_level() > 0) {
ob_end_clean();
}
if (!headers_sent()) {
http_response_code($code);
header('Content-Type: text/html; charset=UTF-8');
header('Cache-Control: no-cache, no-store, must-revalidate');
}
$title = htmlspecialchars((string) $meta['title'], ENT_QUOTES, 'UTF-8');
$message = htmlspecialchars((string) $meta['message'], ENT_QUOTES, 'UTF-8');
$href = htmlspecialchars($base . '/', ENT_QUOTES, 'UTF-8');
echo '<!doctype html><html lang="fr"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>' . $title . '</title></head><body><main><h1>' . $title . '</h1><p>' . $message . '</p><p><a href="' . $href . '">Retour à l\'accueil</a></p></main></body></html>';
}
function app_bootstrap_errors(Base $f3): void
{
// En dev, ne pas poser ONERROR : le handler par défaut de F3
// affiche la stack trace complète quand DEBUG > 0.
if (!app_is_prod()) {
return;
}
register_shutdown_function(function (): void {
$error = error_get_last();
if ($error === null) {
return;
}
$fatalTypes = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR];
if (!in_array($error['type'] ?? 0, $fatalTypes, true)) {
return;
}
app_render_error_fallback(500);
});
$f3->set('ONERROR', function (Base $f3): void {
$code = max((int) ($f3->get('ERROR.code') ?? 500), 1);
$f3->expire(0);
$f3->status($code);
$meta = app_error_meta($code);
$f3->mset([
'errorCode' => $code,
'errorTitle' => $meta['title'],
'errorMessage' => $meta['message'],
]);
try {
echo Template::instance()->render('errors/error.html');
} catch (Throwable) {
app_render_error_fallback($code);
}
});
}