This commit is contained in:
2025-11-01 18:24:35 +01:00
parent 62cf15ab8b
commit 8ce52971a9
8 changed files with 354 additions and 16 deletions

View File

@@ -1 +1,46 @@
Mini-Projet de Développement Web - CMS Simplifié
# Mini-Projet : CMS Simplifié (PHP-SQL)
Ce projet est un système de gestion de contenu (CMS) simple réalisé en PHP pur et sql. Il utilise l'extension PDO pour des requêtes sécurisées vers une base de données MySQL.
L'application est divisée en deux parties :
1. Une **Zone Publique** pour consulter les articles.
2. Une **Zone Administration** protégée par mot de passe, qui permet la gestion complète (CRUD) des articles.
## 🚀 Procédure d'installation
Pour installer et lancer ce projet en local, vous aurez besoin d'un environnement serveur (MAMP, XAMPP, WAMP, Docker, etc.) supportant PHP et MySQL.
1. **Code Source**
* Clonez ou téléchargez ce dépôt et placez le dossier `my_sql_projet` dans le répertoire web de votre serveur (ex: `htdocs/`).
2. **Base de Données**
* Ouvrez votre outil de gestion de base de données (comme phpMyAdmin).
* Créez une nouvelle base de données. Le nom attendu est `my_sql_projet`.
* Sélectionnez cette base de données et importez le fichier `sql/tables.sql`. Ce script créera les tables `articles` et `utilisateur`, et insérera l'administrateur par défaut.
3. **Configuration de la Connexion**
* Dans le dossier `php/`, trouvez le fichier `pdo.example.php`.
* **Copiez-le** et **renommez** la copie en `pdo.php`.
* Ouvrez `pdo.php` et modifiez la variable `$pass` pour y mettre votre propre mot de passe de base de données (ex: `"root"` pour MAMP).
4. **Lancement**
* C'est terminé ! Vous pouvez maintenant accéder au site public via `http://localhost/my_sql_projet/` et à la page de connexion admin via `http://localhost/my_sql_projet/login.php`.
## 🔑 Identifiants de Connexion
Un compte administrateur est créé par défaut par le script `tables.sql` pour vous permettre de tester la zone d'administration.
* **Login :** `admin`
* **Mot de passe :** `admin123` (ou celui que vous avez généré)
## 🏛️ Architecture du Projet
* **Langage :** PHP pur (orienté script, sans framework).
* **Base de Données :** MySQL.
* **Connexion :** L'extension **PDO** est utilisée pour toutes les interactions avec la base de données.
* **Sécurité :**
* **Mots de passe :** Hachage systématique avec `password_hash()` et vérification avec `password_verify()`, comme exigé.
* **Injections SQL :** Prévention totale grâce à l'utilisation exclusive de **requêtes préparées** (avec `prepare()` et `execute()`).
* **Failles XSS :** Protection lors de l'affichage des données avec `htmlspecialchars()`.
* **Zone Admin :** Toutes les pages d'administration (`dashboard.php`, `creer_article.php`, etc.) sont protégées et vérifient l'existence d'une `$_SESSION` active, redirigeant vers `login.php` si l'utilisateur n'est pas authentifié.
* **Gestion des Erreurs :** La page `article.php` gère les ID invalides ou inexistants en affichant un message d'erreur, comme demandé.

View File

@@ -34,10 +34,6 @@ if ($article === false) {
<article>
<h1><?php print htmlspecialchars($article['titre']); ?></h1>
<p>
<em>Publié le : <?php print $article['date_creation']; ?></em>
</p>
<div>
<?php
print nl2br(htmlspecialchars($article['contenu']));

76
creation_article.php Normal file
View File

@@ -0,0 +1,76 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!empty($_POST['titre']) && !empty($_POST['contenu'])) {
$titre = $_POST['titre'];
$contenu = $_POST['contenu'];
require_once 'php/pdo.php';
$sql = "INSERT INTO articles (titre, contenu, date_creation) VALUES (?, ?, NOW())";
$stmt = $pdo->prepare($sql);
$stmt->execute([$titre, $contenu]);
header('Location: dashboard.php');
exit;
} else {
$erreur_message = "Veuillez remplir le titre et le contenu.";
}
}
?>
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Ajouter un article - Admin</title>
</head>
<body>
<header>
<h1>Ajouter un nouvel article</h1>
<p>
Connecté en tant que <?php print htmlspecialchars($_SESSION['user_login']); ?>
| <a href="dashboard.php">Retour au Tableau de Bord</a>
| <a href="logout.php">Se déconnecter</a>
</p>
</header>
<hr>
<main>
<?php if (isset($erreur_message)) : ?>
<div>
<p><?php print $erreur_message; ?></p>
</div>
<?php endif; ?>
<form action="creation_article.php" method="POST">
<div>
<label for="titre">Titre de l'article :</label><br>
<input type="text" id="titre" name="titre">
</div>
<br>
<div>
<label for="contenu">Contenu :</label><br>
<textarea id="contenu" name="contenu" rows="15" cols="80"></textarea>
</div>
<br>
<div>
<button type="submit">Publier l'article</button>
</div>
</form>
</main>
</body>
</html>

View File

@@ -6,9 +6,13 @@ if (!isset($_SESSION['user_id'])) {
exit;
}
$user_login = $_SESSION['user_login'];
require_once 'php/pdo.php';
$sql = "SELECT * FROM articles ORDER BY date_creation DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
@@ -19,21 +23,46 @@ $user_login = $_SESSION['user_login'];
<header>
<h1>Tableau de Bord</h1>
<p>Bienvenue, <?php echo htmlspecialchars($user_login); ?> ! (ID: <?php echo $_SESSION['user_id']; ?>)</p>
<nav>
<a href="logout.php">Se déconnecter</a>
</nav>
<p>
Connecté en tant que <?php print htmlspecialchars($_SESSION['user_login']); ?>
| <a href="logout.php">Se déconnecter</a>
</p>
</header>
<hr>
<main>
<h2>Gestion des articles</h2>
<p>C'est ici que vous pourrez bientôt gérer vos articles.</p>
<a href="creation_article.php">Ajouter un nouvel article</a>
<ul>
<li><a href="creer_article.php">Ajouter un nouvel article</a></li>
</ul>
<hr>
<h3>Vos articles publiés</h3>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>Titre</th>
<th>Date de création</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($articles as $article) : ?>
<tr>
<td><?php echo $article['id']; ?></td>
<td><?php echo htmlspecialchars($article['titre']); ?></td>
<td><?php echo $article['date_creation']; ?></td>
<td>
<a href="modif.php?id=<?php echo $article['id']; ?>">Modifier</a>
|
<a href="supp.php?id=<?php echo $article['id']; ?>">Supprimer</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</main>
</body>

View File

@@ -14,7 +14,7 @@ $stmt->execute();
<body>
<h1>Mini projet</h1>
<p>Bienvenue . Voici les derniers articles :</p>
<p>Bienvenue voici les derniers articles :</p>
<hr>
@@ -25,6 +25,10 @@ $stmt->execute();
<article>
<h2><?php print htmlspecialchars($article['titre']); ?></h2>
<p>
<em>Publié le : <?php print $article['date_creation']; ?></em>
</p>
<p>
<?php
print htmlspecialchars(substr($article['contenu'], 0, 200));

94
modif.php Normal file
View File

@@ -0,0 +1,94 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
require_once 'php/pdo.php';
if ( !isset($_GET['id']) || !ctype_digit($_GET['id']) ) {
die("Erreur : ID invalide.");
}
$id_article = $_GET['id'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!empty($_POST['titre']) && !empty($_POST['contenu'])) {
$nouveau_titre = $_POST['titre'];
$nouveau_contenu = $_POST['contenu'];
$sql = "UPDATE articles SET titre = ?, contenu = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$nouveau_titre, $nouveau_contenu, $id_article]);
header('Location: dashboard.php');
exit;
} else {
$erreur_message = "Veuillez remplir le titre et le contenu.";
}
}
try {
$sql_select = "SELECT * FROM articles WHERE id = ?";
$stmt_select = $pdo->prepare($sql_select);
$stmt_select->execute([$id_article]);
$article = $stmt_select->fetch(PDO::FETCH_ASSOC);
if ($article === false) {
die("Erreur : Cet article n'existe pas.");
}
} catch (PDOException $e) {
die("Erreur : " . $e->getMessage());
}
?>
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Modifier l'article - Admin</title>
</head>
<body>
<header>
<h1>Modifier l'article</h1>
<p>
<a href="dashboard.php">← Retour au Tableau de Bord</a>
| <a href="logout.php">Se déconnecter</a>
</p>
</header>
<hr>
<main>
<?php if (isset($erreur_message)) : ?>
<div>
<p><?php print $erreur_message; ?></p>
</div>
<?php endif; ?>
<form action="modif.php?id=<?php print $article['id']; ?>" method="POST">
<div>
<label for="titre">Titre de l'article :</label><br>
<input type="text" id="titre" name="titre"
value="<?php print htmlspecialchars($article['titre']); ?>">
</div>
<br>
<div>
<label for="contenu">Contenu :</label><br>
<textarea id="contenu" name="contenu" rows="15" cols="80"><?php print htmlspecialchars($article['contenu']); ?></textarea>
</div>
<br>
<div>
<button type="submit">Mettre à jour l'article</button>
</div>
</form>
</main>
</body>
</html>

14
php/pdo.example.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
$serveur = "localhost";
$dbname = "my_sql_projet";
$user = "root";
$pass = "vous devez mettre votre mdp ici";
try {
$pdo = new PDO("mysql:host=$serveur;dbname=$dbname", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
print "Erreur de connexion à la BDD : " . $e->getMessage();
die();
}
?>

80
supp.php Normal file
View File

@@ -0,0 +1,80 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
require_once 'php/pdo.php';
if ( !isset($_GET['id']) || !ctype_digit($_GET['id']) ) {
die("Erreur : ID invalide.");
}
$id_article = $_GET['id'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['id']) && $_POST['id'] == $id_article) {
$sql = "DELETE FROM articles WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id_article]);
header('Location: dashboard.php');
exit;
}
}
try {
$sql_select = "SELECT titre FROM articles WHERE id = ?";
$stmt_select = $pdo->prepare($sql_select);
$stmt_select->execute([$id_article]);
$article = $stmt_select->fetch(PDO::FETCH_ASSOC);
if ($article === false) {
die("Erreur : Cet article n'existe pas.");
}
} catch (PDOException $e) {
die("Erreur : " . $e->getMessage());
}
?>
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Supprimer l'article - Admin</title>
</head>
<body>
<header>
<h1>Confirmer la suppression</h1>
<p>
<a href="dashboard.php">← Annuler et Retourner au Tableau de Bord</a>
</p>
</header>
<hr>
<main>
<p>Voulez-vous vraiment supprimer l'article suivant ?</p>
<h2><?php print htmlspecialchars($article['titre']); ?></h2>
<p>Cette action est irréversible.</p>
<form action="supp.php?id=<?php print $id_article; ?>" method="POST">
<input type="hidden" name="id" value="<?php print $id_article; ?>">
<button type="submit">
OUI
</button>
</form>
<br>
<button type="submit">
<a href="dashboard.php">NON</a>
</button>
</main>
</body>
</html>