From ab8ac6b7fb037afcbcb9651d43e50c8cb3721094 Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 4 Mar 2026 03:49:11 +0100 Subject: [PATCH] replaced eloquent by redbeanphp --- README.md | 2 +- composer.json | 19 +-- migrate.php | 36 ------ public/index.php | 65 +++++++---- src/Config/redbean.php | 19 +++ src/Controllers/PostController.php | 79 +++++++++++++ src/Controllers/placer_ici_logique_metier.txt | 0 src/Middleware/AuthMiddleware.php | 2 + src/Middleware/placer_ici_middleware.txt | 0 src/Models/Post.php | 110 ++++++++++++++++-- src/Routes/admin.php | 83 ------------- src/Routes/admin.routes.php | 24 ++++ src/Routes/home.php | 22 ---- src/Routes/home.routes.php | 17 +++ 14 files changed, 297 insertions(+), 181 deletions(-) delete mode 100644 migrate.php create mode 100644 src/Config/redbean.php create mode 100644 src/Controllers/PostController.php delete mode 100644 src/Controllers/placer_ici_logique_metier.txt create mode 100644 src/Middleware/AuthMiddleware.php delete mode 100644 src/Middleware/placer_ici_middleware.txt delete mode 100644 src/Routes/admin.php create mode 100644 src/Routes/admin.routes.php delete mode 100644 src/Routes/home.php create mode 100644 src/Routes/home.routes.php diff --git a/README.md b/README.md index 33391dd..22ee4df 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ * [PHP](https://www.php.net) comme language * [Slim](https://www.slimframework.com) comme framework -* [Eloquent](https://github.com/illuminate/database) comme ORM +* [RedBeanPHP](https://www.redbeanphp.com/index.php) comme ORM * [Twig](https://twig.symfony.com) comme template engine ## HOWTO diff --git a/composer.json b/composer.json index ff02b3c..dddcbda 100644 --- a/composer.json +++ b/composer.json @@ -12,14 +12,15 @@ ], "require": { "slim/slim": "4.*", - "slim/psr7":"*", - "illuminate/database":"*", - "twig/twig":"*", - "slim/twig-view":"*" - }, - "autoload": { - "psr-4": { - "App\\": "src/" + "slim/psr7": "*", + "gabordemooij/redbean": "^5.7", + "twig/twig": "*", + "slim/twig-view": "*", + "php-di/php-di": "^7.1" + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } } - } } diff --git a/migrate.php b/migrate.php deleted file mode 100644 index 79a1c48..0000000 --- a/migrate.php +++ /dev/null @@ -1,36 +0,0 @@ -addConnection([ - 'driver' => 'sqlite', - // __DIR__ pointe sur le répertoire racine du projet - // le fichier SQLite se trouve dans le sous‑dossier `database` - 'database' => realpath(__DIR__ . '/database/blog.sqlite'), - 'prefix' => '', -]); - -$capsule->setAsGlobal(); -$capsule->bootEloquent(); - -// --------------------------------------------------------------------- -// Création de la table `posts` si elle n'existe pas déjà -// --------------------------------------------------------------------- -if (!Capsule::schema()->hasTable('posts')) { - Capsule::schema()->create('posts', function ($table) { - $table->increments('id'); // clé primaire auto‑incrémentée - $table->string('title'); // titre de l'article - $table->text('content'); // contenu de l'article - }); - echo "Table 'posts' créée avec succès.\n"; -} else { - echo "La table 'posts' existe déjà.\n"; -} diff --git a/public/index.php b/public/index.php index 35b6f49..66797f3 100644 --- a/public/index.php +++ b/public/index.php @@ -1,61 +1,80 @@ addDefinitions([ + + // ----------------------------------------------------------------- + // Twig : création de l’instance Slim\Views\Twig + // ----------------------------------------------------------------- + Twig::class => function () { + $loader = new FilesystemLoader(__DIR__ . '/../views'); + $settings = ['cache' => false]; // désactiver le cache en dev + return new Twig($loader, $settings); + }, + + // ----------------------------------------------------------------- + // Ajoute d’autres services ici si besoin (logger, DB, etc.) + // ----------------------------------------------------------------- +]); + +$container = $containerBuilder->build(); + +/* ------------------------------------------------- + Instanciation de l’application Slim avec le container + ------------------------------------------------- */ +AppFactory::setContainer($container); $app = AppFactory::create(); /* ------------------------------------------------- - Middleware d’erreur (affiche les exceptions) + Middleware d’erreur ------------------------------------------------- */ $app->addErrorMiddleware(true, true, true); /* ------------------------------------------------- - Twig (templates) + Twig middleware – on récupère explicitement le service Twig ------------------------------------------------- */ -$twig = Twig::create(__DIR__ . '/../views', ['cache' => false]); -$app->add(TwigMiddleware::create($app, $twig)); +$twig = $container->get(Twig::class); // <-- récupération directe +$app->add(TwigMiddleware::create($app, $twig)); // <-- utilisation de create(), pas createFromContainer() /* ------------------------------------------------- - Vérification / création du fichier SQLite + Vérification / création du fichier SQLite ------------------------------------------------- */ $dbFile = __DIR__ . '/../database/blog.sqlite'; if (!file_exists($dbFile)) { - // crée un fichier vide et lui donne les permissions d’écriture touch($dbFile); chmod($dbFile, 0664); } /* ------------------------------------------------- - Eloquent (connexion SQLite) + RedBeanPHP (connexion SQLite) ------------------------------------------------- */ -$capsule = new Capsule; -$capsule->addConnection([ - 'driver' => 'sqlite', - // le chemin relatif fonctionne ; SQLite créera le fichier si besoin - 'database' => $dbFile, - 'prefix' => '', -]); -$capsule->setAsGlobal(); -$capsule->bootEloquent(); +require __DIR__ . '/../src/Config/redbean.php'; +initRedBean($dbFile); /* ------------------------------------------------- - Chargement des routes + Chargement des routes ------------------------------------------------- */ -$routerFiles = glob(__DIR__ . '/../src/Routes/*.php'); -foreach ($routerFiles as $file) { - (require $file)($app); // chaque fichier retourne une fonction qui ajoute ses routes +foreach (glob(__DIR__ . '/../src/Routes/*.routes.php') as $file) { + (require $file)($app); } /* ------------------------------------------------- - Démarrage de l’application + Démarrage de l’application ------------------------------------------------- */ $app->run(); diff --git a/src/Config/redbean.php b/src/Config/redbean.php new file mode 100644 index 0000000..a87f179 --- /dev/null +++ b/src/Config/redbean.php @@ -0,0 +1,19 @@ +view = $view; + } + + /** Page publique – liste des articles */ + public function index(Request $request, Response $response): Response + { + $posts = Post::allDesc(); + return $this->view->render($response, 'pages/home.twig', ['posts' => $posts]); + } + + /** Tableau de bord admin */ + public function admin(Request $request, Response $response): Response + { + $posts = Post::allDesc(); + return $this->view->render($response, 'pages/admin.twig', ['posts' => $posts]); + } + + /** Formulaire création / édition */ + public function form(Request $request, Response $response, array $args): Response + { + $id = (int)($args['id'] ?? 0); + $post = $id ? Post::find($id) : null; // id=0 → création + + $action = $id ? "/admin/edit/{$id}" : "/admin/create"; + + return $this->view->render($response, 'pages/post_form.twig', [ + 'action' => $action, + 'post' => $post, + ]); + } + + /** Enregistrement d’un nouvel article */ + public function create(Request $request, Response $response): Response + { + $data = $request->getParsedBody(); + $post = Post::make($data); + $post->save(); + + return $response->withHeader('Location', '/admin')->withStatus(302); + } + + /** Mise à jour d’un article existant */ + public function update(Request $request, Response $response, array $args): Response + { + $post = Post::find((int)$args['id']); + $post->updateFromArray($request->getParsedBody()); + $post->save(); + + return $response->withHeader('Location', '/admin')->withStatus(302); + } + + /** Suppression d’un article */ + public function delete(Request $request, Response $response, array $args): Response + { + $post = Post::find((int)$args['id']); + $post->delete(); + + return $response->withHeader('Location', '/admin')->withStatus(302); + } +} diff --git a/src/Controllers/placer_ici_logique_metier.txt b/src/Controllers/placer_ici_logique_metier.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php new file mode 100644 index 0000000..2c20b18 --- /dev/null +++ b/src/Middleware/AuthMiddleware.php @@ -0,0 +1,2 @@ +bean = $bean; + } + + /* ------------------------------------------------- + FACTORIES + ------------------------------------------------- */ + + /** Crée un nouveau post à partir d’un tableau de données */ + public static function make(array $data): self + { + $bean = R::dispense('post'); + $bean->title = $data['title'] ?? ''; + $bean->content = $data['content'] ?? ''; + return new self($bean); + } + + /** Charge un post existant (lève une exception s’il n’existe pas) */ + public static function find(int $id): self + { + $bean = R::load('post', $id); + if ($bean->id === 0) { + throw new \RuntimeException("Post {$id} introuvable"); + } + return new self($bean); + } + + /** Retourne tous les posts, triés par id décroissant */ + public static function allDesc(): array + { + $beans = R::findAll('post', ' ORDER BY id DESC '); + return array_map(fn(OODBBean $b) => new self($b), $beans); + } + + /* ------------------------------------------------- + PERSISTENCE + ------------------------------------------------- */ + + /** Enregistre (INSERT ou UPDATE) le bean */ + public function save(): void + { + R::store($this->bean); + } + + /** Supprime le bean de la base */ + public function delete(): void + { + R::trash($this->bean); + } + + /* ------------------------------------------------- + ACCESSEURS / MUTATEURS + ------------------------------------------------- */ + + public function getId(): int { return (int) $this->bean->id; } + public function getTitle(): string { return (string) $this->bean->title; } + public function getContent(): string { return (string) $this->bean->content; } + + public function setTitle(string $title): void { $this->bean->title = $title; } + public function setContent(string $content): void { $this->bean->content = $content; } + + /* ------------------------------------------------- + MISE À JOUR À PARTIR D'UN TABLEAU + ------------------------------------------------- */ + + /** + * Met à jour le bean à partir d’un tableau de données. + * + * Seuls les champs connus sont pris en compte ; les clés inconnues + * sont simplement ignorées. Cette méthode facilite l’appel depuis + * le contrôleur : `$post->updateFromArray($request->getParsedBody());` + * + * @param array $data Données du formulaire + */ + public function updateFromArray(array $data): void + { + // titre + if (array_key_exists('title', $data)) { + $this->setTitle((string) $data['title']); + } + + // contenu + if (array_key_exists('content', $data)) { + $this->setContent((string) $data['content']); + } + + // Si d’autres champs sont ajoutés à l’entité (ex. author, status), + // il suffit de les gérer ici de la même façon. + } } diff --git a/src/Routes/admin.php b/src/Routes/admin.php deleted file mode 100644 index 16f95e8..0000000 --- a/src/Routes/admin.php +++ /dev/null @@ -1,83 +0,0 @@ -get('/admin', function (Request $request, Response $response) use ($app) { - $posts = Post::orderByDesc('id')->get(); - - /** @var Twig $view */ - $view = $request->getAttribute('view'); - return $view->render($response, 'pages/admin.twig', ['posts' => $posts]); - }); - - // ------------------------------------------------- - // Création d'un article (POST depuis admin) - // ------------------------------------------------- - $app->post('/admin/create', function (Request $request, Response $response) { - $data = $request->getParsedBody(); - - Post::create([ - 'title' => $data['title'], - 'content' => $data['content'], - ]); - - return $response - ->withHeader('Location', '/admin') - ->withStatus(302); - }); - - // ------------------------------------------------- - // Formulaire d'édition (GET depuis admin) - // ------------------------------------------------- - $app->get('/admin/edit/{id}', function (Request $request, Response $response, $args) use ($app) { - $id = (int)$args['id']; - $post = $id ? Post::findOrFail($id) : null; // id=0 → création - - /** @var Twig $view */ - $view = $request->getAttribute('view'); - - return $view->render($response, 'pages/post_form.twig', [ - 'action' => $id ? "/admin/edit/{$id}" : "/admin/create", - 'post' => $post, - ]); - }); - - // ------------------------------------------------- - // Enregistrement des modifications (POST depuis admin) - // ------------------------------------------------- - $app->post('/admin/edit/{id}', function (Request $request, Response $response, $args) { - $post = Post::findOrFail($args['id']); - $data = $request->getParsedBody(); - - $post->update([ - 'title' => $data['title'], - 'content' => $data['content'], - ]); - - return $response - ->withHeader('Location', '/admin') - ->withStatus(302); - }); - - // ------------------------------------------------- - // Suppression d'un article (POST depuis admin) - // ------------------------------------------------- - $app->post('/admin/delete/{id}', function (Request $request, Response $response, $args) { - $post = Post::findOrFail($args['id']); - $post->delete(); - - return $response - ->withHeader('Location', '/admin') - ->withStatus(302); - }); -}; diff --git a/src/Routes/admin.routes.php b/src/Routes/admin.routes.php new file mode 100644 index 0000000..81a6eba --- /dev/null +++ b/src/Routes/admin.routes.php @@ -0,0 +1,24 @@ +get('/admin', [PostController::class, 'admin']); + + // Formulaire de création + $app->get('/admin/create', [PostController::class, 'form']); + $app->post('/admin/create', [PostController::class, 'create']); + + // Formulaire d'édition – l'ID doit être fourni dans l'URL + $app->get('/admin/edit/{id}', [PostController::class, 'form']); + $app->post('/admin/edit/{id}', [PostController::class, 'update']); + + // Suppression d'un post + $app->post('/admin/delete/{id}', [PostController::class, 'delete']); +}; diff --git a/src/Routes/home.php b/src/Routes/home.php deleted file mode 100644 index 297e39a..0000000 --- a/src/Routes/home.php +++ /dev/null @@ -1,22 +0,0 @@ -get('/', function (Request $request, Response $response) use ($app) { - $posts = Post::orderByDesc('id')->get(); - - /** @var Twig $view */ - $view = $request->getAttribute('view'); // <-- récupération correcte - return $view->render($response, 'pages/home.twig', ['posts' => $posts]); - }); -}; diff --git a/src/Routes/home.routes.php b/src/Routes/home.routes.php new file mode 100644 index 0000000..9f6caea --- /dev/null +++ b/src/Routes/home.routes.php @@ -0,0 +1,17 @@ +get('/', [PostController::class, 'index']); +};