This commit is contained in:
julien
2026-03-09 10:40:35 +01:00
parent 393561f6b0
commit 4b2b7da9b4
2 changed files with 98 additions and 29 deletions

View File

@@ -1,2 +1,10 @@
# Environnement de l'application
APP_ENV=development
# APP_ENV=production
# Chemin de cache Twig (laisser vide en développement pour désactiver le cache)
# Exemples :
# TWIG_CACHE=var/cache/twig
# TWIG_CACHE=/srv/www/myapp/var/cache/twig
TWIG_CACHE=
# (Optionnel) autres variables d'environnement peuvent être ajoutées ici

View File

@@ -12,15 +12,23 @@ use Medoo\Medoo;
use Dotenv\Dotenv;
use Throwable;
// Charger .env (tolérant l'absence du fichier)
/**
* Charger les variables d'environnement si présentes (tolérant l'absence du fichier).
*/
$dotenv = Dotenv::createImmutable(__DIR__ . '/../');
$dotenv->safeLoad();
// Configuration centralisée (valeurs raisonnables par défaut)
/**
* Configuration centrale avec valeurs par défaut raisonnables.
*
* - 'env' : environnement d'exécution ('production' par défaut)
* - 'twig.cache' : résolu plus bas à partir de TWIG_CACHE ou par défaut selon l'environnement
* - 'db.file' et 'db.file_mode' : fichier SQLite et permissions
*/
$config = [
'env' => strtolower($_ENV['APP_ENV'] ?? $_SERVER['APP_ENV'] ?? 'production'),
'env' => strtolower((string) ($_ENV['APP_ENV'] ?? $_SERVER['APP_ENV'] ?? 'production')),
'twig' => [
'cache' => false, // => mettre un chemin en production, ex: __DIR__ . '/../var/cache/twig'
'cache' => null,
],
'db' => [
'file' => __DIR__ . '/../database/app.sqlite',
@@ -28,9 +36,25 @@ $config = [
],
];
$isDebug = ($config['env'] === 'development' || $config['env'] === 'dev');
/**
* Résolution de la valeur twig.cache depuis la variable d'environnement TWIG_CACHE.
* Si TWIG_CACHE est vide : false en dev, chemin par défaut en production.
*/
$envTwigCache = $_ENV['TWIG_CACHE'] ?? $_SERVER['TWIG_CACHE'] ?? null;
if ($envTwigCache !== null && $envTwigCache !== '') {
$config['twig']['cache'] = (string) $envTwigCache;
} else {
$devEnvs = ['development', 'dev'];
$config['twig']['cache'] = in_array($config['env'], $devEnvs, true)
? false
: __DIR__ . '/../var/cache/twig';
}
// Affichage des erreurs selon l'environnement
$isDebug = in_array($config['env'], ['development', 'dev'], true);
/**
* Affichage et rapport d'erreurs selon l'environnement.
*/
if ($isDebug) {
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
@@ -44,26 +68,36 @@ if ($isDebug) {
// -------------------------
// Base de données (SQLite)
// -------------------------
$dbFile = $config['db']['file'];
/**
* Créer le fichier de base de données si nécessaire et appliquer les permissions.
*/
if (!file_exists($dbFile)) {
if (!is_dir(dirname($dbFile))) {
mkdir(dirname($dbFile), 0755, true);
$dbDir = dirname($dbFile);
if (!is_dir($dbDir)) {
mkdir($dbDir, 0755, true);
}
touch($dbFile);
chmod($dbFile, $config['db']['file_mode']);
@chmod($dbFile, $config['db']['file_mode']);
}
// Options Medoo (SQLite)
/**
* Options Medoo pour SQLite.
*/
$medooOptions = [
'database_type' => 'sqlite',
'database_file' => $dbFile,
'database_name' => $dbFile, // nécessaire pour certaines versions de Medoo
'database_name' => $dbFile,
'charset' => 'utf8',
];
// Instancier Medoo
/** @var Medoo $database */
$database = new Medoo($medooOptions);
// Créer la table si nécessaire (schéma minimal)
/**
* Schéma minimal : création de la table 'post' si elle n'existe pas.
*/
$database->query(
<<<'SQL'
CREATE TABLE IF NOT EXISTS post (
@@ -77,25 +111,37 @@ SQL
// -------------------------
// Services (container simple)
// -------------------------
/** @var array{view: Twig, postRepository: \App\Repositories\PostRepositoryMedoo} $container */
/**
* Container simple (table associative de services).
*
* @var array<string, mixed> $container
*/
$container = [];
/**
* Construire les services et les retourner dans le container.
*
* Reste modulaire : la fonction reste locale et conserve la variable $container = [].
* Cette fonction reste locale pour préserver l'encapsulation.
*
* @param array $config
* @param Medoo $database
* @return array
* @return array<string, mixed>
*/
$container = (function (array $config, Medoo $database): array {
$container = (static function (array $config, Medoo $database): array {
$services = [];
// Vue Twig
$services['view'] = new Twig(new FilesystemLoader(__DIR__ . '/../views'), ['cache' => $config['twig']['cache']]);
// Résoudre le cache Twig et créer le dossier si nécessaire.
$twigCache = $config['twig']['cache'];
if ($twigCache && $twigCache !== false && !is_dir((string) $twigCache)) {
mkdir((string) $twigCache, 0755, true);
}
// Repository Post (Medoo)
// Vue Twig
$loader = new FilesystemLoader(__DIR__ . '/../views');
$services['view'] = new Twig($loader, ['cache' => $config['twig']['cache']]);
// Repository Post (implémentation Medoo)
$services['postRepository'] = new App\Repositories\PostRepositoryMedoo($database);
return $services;
@@ -104,16 +150,21 @@ $container = (function (array $config, Medoo $database): array {
// -------------------------
// Slim app
// -------------------------
$app = AppFactory::create();
// Error middleware
/**
* Middleware d'erreurs.
*
* Les trois flags correspondent à : displayErrorDetails, logErrors, logErrorDetails.
*/
$errorMiddleware = $app->addErrorMiddleware($isDebug, $isDebug, $isDebug);
if (!$isDebug) {
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
// Renderer générique en production
$errorHandler->registerErrorRenderer('text/html', function (Throwable $exception, bool $displayErrorDetails) {
return '<html><head><meta charset="utf-8"><title>Erreur</title></head><body><h1>Erreur serveur</h1><p>Une erreur est survenue. Veuillez réessayer plus tard.</p></body></html>';
// Renderer HTML générique en production pour masquer les détails d'exception.
$errorHandler->registerErrorRenderer('text/html', static function (Throwable $exception, bool $displayErrorDetails): string {
return '<!doctype html><html lang="fr"><head><meta charset="utf-8"><title>Erreur</title></head><body><h1>Erreur serveur</h1><p>Une erreur est survenue. Veuillez réessayer plus tard.</p></body></html>';
});
}
@@ -121,8 +172,18 @@ if (!$isDebug) {
$app->addBodyParsingMiddleware();
$app->add(TwigMiddleware::create($app, $container['view']));
// Charger routes (web.php reçoit le container)
(require __DIR__ . '/../src/Routes/web.php')($app, $container);
/**
* Charger les routes : le fichier web.php reçoit l'application et le container.
* On utilise require pour que toute exception remonte à Slim / au handler d'erreurs.
*/
$routesPath = __DIR__ . '/../src/Routes/web.php';
if (file_exists($routesPath)) {
/** @var callable $routes */
$routes = require $routesPath;
$routes($app, $container);
} else {
// En cas d'absence du fichier de routes, on peut laisser l'application démarrer sans routes.
// (Conserver le comportement antérieur — aucune exception levée ici)
}
// Lancer l'app
$app->run();