100%
This commit is contained in:
47
README.md
47
README.md
@@ -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é.
|
||||
@@ -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
76
creation_article.php
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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
94
modif.php
Normal 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
14
php/pdo.example.php
Normal 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
80
supp.php
Normal 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>
|
||||
Reference in New Issue
Block a user