CodeIgniter 4 gestion de contenu

Un blog complet en CodeIgniter 4 : le modèle, la migration, les contrôleurs, le CRUD et les gabarits, pièce par pièce.

Versions de ce cours

Ce cours est écrit et vérifié sur CodeIgniter 4.7.4 avec PHP 8.4.22, le 16 août 2026. Le site que vous lisez tourne, lui, en CodeIgniter 4.6.1 : rien de ce qui est enseigné ici ne diffère entre les deux versions.

Architecture MVC pour la Gestion de Contenu

Comprenez comment structurer votre application de gestion de contenu avec le pattern MVC de CodeIgniter 4.

Pattern MVC pour un CMS

Modèle (Model)

  • Gestion des données
  • Interactions avec la base
  • Validation des données
  • Logique métier

Vue (View)

  • Interface utilisateur
  • Affichage des données
  • Templates HTML
  • Présentation

Contrôleur (Controller)

  • Logique de l'application
  • Gestion des requêtes
  • Coordination M-V
  • Routage

Structure des Fichiers CMS

php

app/
  ├── Controllers/
      ├── Articles.php
      ├── Categories.php
      ├── Admin/
          └── Dashboard.php
  ├── Models/
      ├── ArticleModel.php
      ├── CategoryModel.php
      └── UserModel.php
  ├── Views/
      ├── articles/
      ├── admin/
      └── templates/

Création des Modèles

Découvrez comment créer des modèles robustes pour gérer vos données de contenu.

Modèle Article

php

<?php
namespace App\Models;
use CodeIgniter\Model;
class ArticleModel extends Model
{
    protected $table = 'articles';
    protected $primaryKey = 'id';
    protected $allowedFields = [
        'title', 'slug', 'content',
        'excerpt', 'category_id', 'status',
        'featured_image', 'published_at'
    ];
    protected $useTimestamps = true;
    protected $validationRules = [
        'title' => 'required|min_length[3]|max_length[255]',
        'content' => 'required|min_length[10]',
        'category_id' => 'required|numeric'
    ];
    // Méthodes personnalisées
    public function getPublishedArticles()
    {
        return $this->where('status', 'published')
                        ->orderBy('published_at', 'DESC')
                        ->findAll();
    }
}

Migration de Base de Données

php

// app/Database/Migrations/2026-08-16-141208_CreateArticlesTable.php
public function up()
{
    $this->forge->addField([
        'id' => [
            'type'           => 'INT',
            'auto_increment' => true
        ],
        'title' => [
            'type'       => 'VARCHAR',
            'constraint' => 255
        ],
        'slug' => [
            'type'       => 'VARCHAR',
            'constraint' => 255,
            'unique'     => true
        ],
        'content'        => ['type' => 'TEXT'],
        'excerpt'        => ['type' => 'TEXT', 'null' => true],
        'category_id'    => ['type' => 'INT'],
        'featured_image' => [
            'type'       => 'VARCHAR',
            'constraint' => 255,
            'null'       => true
        ],
        'status' => [
            'type'       => 'ENUM',
            'constraint' => ['draft', 'published'],
            'default'    => 'draft'
        ],
        'published_at' => ['type' => 'DATETIME', 'null' => true],
        'created_at'   => ['type' => 'DATETIME', 'null' => true],
        'updated_at'   => ['type' => 'DATETIME', 'null' => true]
    ]);
    $this->forge->addKey('id', true);
    $this->forge->createTable('articles');
}

Les deux dernières colonnes ne sont pas décoratives : created_at et updated_at portent exactement les noms que $useTimestamps = true attend. Le modèle les remplit tout seul à chaque save() — mais il faut que la migration les ait créées, sans quoi l’enregistrement échoue.

Le type ENUM est propre à MySQL. SQLite l’accepte en silence et stocke du texte sans rien vérifier ; PostgreSQL le refuse. Une même migration, trois comportements — c’est le genre de ligne qui ne se voit qu’au changement de base.

Contrôleurs de Gestion

Implémentez la logique métier avec des contrôleurs bien structurés.

Contrôleur Articles

php

<?php
namespace App\Controllers;
class Articles extends BaseController
{
    protected $articleModel;
    public function __construct()
    {
        $this->articleModel = new \App\Models\ArticleModel();
    }
    // Afficher la liste des articles
    public function index()
    {
        $data = [
            'articles' => $this->articleModel->getPublishedArticles(),
            'title' => 'Tous les Articles'
        ];
        return view('articles/index', $data);
    }
    // Afficher un article
    public function show($slug)
    {
        $article = $this->articleModel->where('slug', $slug)
                        ->first();
        if (!$article) {
            throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
        }
        return view('articles/show', ['article' => $article]);
    }
}

Le troisième paramètre d’url_title() passe le résultat en minuscules. Sans lui, « Mon Premier Article » devient Mon-Premier-Article : une adresse qui marche, jusqu’au jour où deux systèmes la comparent différemment. Il règle la casse, et elle seule — « Deuxième article » donne deuxième-article, l’accent survit. Les deux comportements sont vérifiés à l’exécution.

Le test $this->request->getMethod() === 'POST' est juste : depuis CodeIgniter 4, cette méthode rend toujours des majuscules. Depuis la version 4.3, on écrit plus volontiers $this->request->is('post'), qui dit la même chose en une lecture.

Contrôleur Admin (CRUD)

Créer un Article :

php

public function create()
{
  if ($this->request->getMethod() === 'POST') {
    $data = $this->request->getPost();
    $data['slug'] = url_title($data['title'], '-', true);
    if ($this->articleModel->save($data)) {
      return redirect()->to('/admin/articles')
              ->with('success', 'Article créé!');
    }
  }
  return view('admin/articles/create');
}

Modifier un Article :

php

public function edit($id)
{
  $article = $this->articleModel->find($id);
  if ($this->request->getMethod() === 'POST') {
    $data = $this->request->getPost();
    if ($this->articleModel->update($id, $data)) {
      return redirect()->to('/admin/articles')
              ->with('success', 'Article modifié!');
    }
  }
  return view('admin/articles/edit', [
    'article' => $article
  ]);
}

Templates et Vues

Créez des interfaces utilisateur dynamiques avec le système de vues de CodeIgniter 4.

Layout Principal

php

<!-- app/Views/layouts/main.php -->
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Mon CMS' ?></title>
</head>
<body>
    <header>
        <?= $this->include('partials/navigation') ?>
    </header>
    <main>
        <?= $this->renderSection('content') ?>
    </main>
    <footer>
        <?= $this->include('partials/footer') ?>
    </footer>
</body>
</html>

Vue Liste d'Articles

php

<!-- app/Views/articles/index.php -->
<?= $this->extend('layouts/main') ?>
<?= $this->section('content') ?>
<div class="container">
    <h1><?= $title ?></h1>
    <?php if (!empty($articles)): ?>
        <div class="articles-grid">
            <?php foreach ($articles as $article): ?>
                <article class="article-card">
                    <h2>
                        <a href="<?= base_url('articles/' . $article['slug']) ?>">
                            <?= esc($article['title']) ?>
                        </a>
                    </h2>
                    <p><?= esc($article['excerpt']) ?></p>
                </article>
            <?php endforeach; ?>
        </div>
    <?php else: ?>
        <p>Aucun article trouvé.</p>
    <?php endif; ?>
</div>
<?= $this->endSection() ?>

Opérations CRUD Complètes

Implémentez les quatre opérations de base : Create, Read, Update, Delete.

C Create - Création

✅ Fonctionnalités : • Formulaire de création • Validation des données • Génération automatique du slug • Upload d'images

POST /admin/articles/create → Validation → Save → Redirect

R Read - Lecture

📖 Fonctionnalités : • Liste paginée des articles • Filtrage par catégorie • Recherche par titre/contenu • Vue détaillée

GET /articles GET /articles/{slug}

U Update - Modification

✏️ Fonctionnalités : • Pré-remplissage du formulaire • Mise à jour partielle • Gestion des versions • Historique des modifications

PUT /admin/articles/{id} → Validation → Update → Redirect

D Delete - Suppression

🗑️ Fonctionnalités : • Confirmation de suppression • Soft delete (corbeille) • Suppression en masse • Restauration possible

DELETE /admin/articles/{id} → Confirmation → Delete → Redirect

Exercice Pratique : Blog CMS

Créez un système de blog complet avec toutes les fonctionnalités apprises.

🎯 Projet Final : Mon Blog CMS

Frontend Public :

✅ Pages à créer : • Page d'accueil avec articles récents • Liste des articles avec pagination • Page détail d'un article • Page catégories • Barre de recherche

🎨 Design : • Design responsive • Navigation intuitive • Système de commentaires • Partage sur les réseaux sociaux

Administration :

⚙️ Panel Admin : • Système d'authentification • Dashboard avec statistiques • CRUD articles complet • Gestion des catégories • Upload d'images

🔧 Fonctionnalités avancées : • Éditeur WYSIWYG • Système de brouillons • Programmation de publication • Gestion des médias • SEO (meta descriptions)

🚀 Code de démarrage :

html

                    &lt;h4 class="font-semibold text-white mb-4"&gt;&lt;/h4&gt;
# Créer les migrations
php spark make:migration CreateArticlesTable
php spark make:migration CreateCategoriesTable
# Créer les modèles
php spark make:model ArticleModel
php spark make:model CategoryModel
# Créer les contrôleurs
php spark make:controller Articles
php spark make:controller Admin/Dashboard

Maîtrisez la Gestion de Contenu ! 🚀

Vous avez maintenant toutes les clés pour créer un CMS robuste avec CodeIgniter 4. Explorez les fonctionnalités avancées pour aller plus loin.

Un CMS, pièce par pièce

Modèle, migration, contrôleur, gabarit : les quatre pièces d’une application CodeIgniter, et le CRUD qui les relie.