├── README.md ├── blog ├── index.php ├── src │ ├── controllers │ │ ├── comment │ │ │ ├── add.php │ │ │ └── update.php │ │ ├── homepage.php │ │ └── post.php │ ├── lib │ │ └── database.php │ └── model │ │ ├── comment.php │ │ └── post.php ├── style.css └── templates │ ├── error.php │ ├── homepage.php │ ├── layout.php │ ├── post.php │ └── update_comment.php └── db.sql /README.md: -------------------------------------------------------------------------------- 1 | # Adoptez une architecture MVC en PHP 2 | 3 | Voici le dépôt Git qui sert de support au cours **Adoptez une architecture MVC en PHP**. À partir de ce dépôt, vous pourrez récupérer le code source, situé dans le dossier `blog/`, à chaque étape de l'avancement du projet. 4 | 5 | Nous vous fournissons une liste de liens Github, dans la section [Étapes](#etapes) de ce document, vers chacune des étapes _précédentes_. Aussi, pour trouver une étape future, vous devrez obligatoirement repasser par la [dernière étape](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php). Si vous souhaitez naviguer dans les étapes directement depuis votre dépôt local, sachez que ce dépôt utilise l'[étiquettage Git](https://git-scm.com/book/fr/v2/Les-bases-de-Git-%C3%89tiquetage) pour définir chaque étape. 6 | 7 | Ce document vous fournira aussi quelques astuces et informations sur la manière d'installer le projet. 8 | 9 | ## Étapes 10 | 11 | * [Appréhendez les limites d'un code de débutant](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/apprehendez-limites-code-debutant) 12 | * [Isolez l'affichage du traitement PHP](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/isolez-affichage-traitement-php) 13 | * [Isolez l'accès aux données](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/isolez-acces-donnees) 14 | * [Soignez la cosmétique](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/soignez-cosmetique) 15 | * [Affichez des commentaires](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/affichez-commentaires) 16 | * [Créez un template de page](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/creez-template-page) 17 | * [Créez un routeur](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/creez-routeur) 18 | * [Ajoutez des commentaires](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/ajoutez-commentaires) 19 | * [Gérez les erreurs](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/gerez-erreurs) 20 | * [Structurez vos données](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/structurez-donnees) 21 | * [Donnez vie à vos structures](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/donnez-vie-structures) 22 | * [Tirez parti de la composition](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/tirez-parti-composition) 23 | * [Utilisez les namespaces](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/utilisez-namespaces) 24 | * [Modifiez un commentaire](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/modifiez-commentaire) 25 | * [Final](https://github.com/OpenClassrooms-Student-Center/4670706-architecture-mvc-php/tree/final) 26 | 27 | ## Installation 28 | 29 | ### Prérequis 30 | 31 | Tout d'abord, ce projet est fait pour fonctionner avec les dernières versions de PHP (actuellement `^8.0`). Il vous faudra donc l'installer sur votre machine. 32 | 33 | De plus, ce projet nécessite l'utilisation d'une base de données MySQL. Vous devrez donc installer ET configurer votre base de données, et créer un utilisateur. Si vous voulez vous rafraîchir la mémoire, vous pouvez relire le chapitre [Mettez en place une base de données avec phpMyAdmin](https://openclassrooms.com/fr/courses/918836-concevez-votre-site-web-avec-php-et-mysql/913893-mettez-en-place-une-base-de-donnees-avec-phpmyadmin) ! Par défaut, l'application utilise une base de données dénommée `blog`, accessible à un utilisateur `blog` dont le mot de passe est `password`. 34 | 35 | ### Configuration 36 | 37 | Une fois que vous avez installé votre serveur MySQL, vous pouvez remplacer les identifiants utilisés dans le code par les votre. Dans le fichier `blog/src/model.php`, à la ligne 5 : 38 | 39 | ```php 40 | $database = new PDO('mysql:host=localhost;dbname=blog;charset=utf8', 'blog', 'password'); 41 | ``` 42 | 43 | Vous devriez aussi remplir votre base de données. Vous pouvez charger le schéma par défaut (et quelques données), contenu dans le fichier `db.sql`. Pour ce faire, vous pouvez utiliser votre interface d'administration MySQL, ou bien lancer la commande suivante, si vous êtes sous Linux : 44 | 45 | ```bash 46 | mysql -ublog -p blog < db.sql 47 | ``` 48 | 49 | ### Lancement 50 | 51 | Vous pouvez utiliser le serveur web intégré à PHP pour lancer ce projet. Placez vous dans le dossier `blog/`, puis lancez la commande `php -S localhost:8080` (vous pouvez choisir le port que vous souhaitez si `8080` est déjà utilisé). 52 | 53 | Alternativement, et si vous avez une _stack_ WAMP ou LAMP installée, vous pouvez configurer votre serveur Apache pour qu'il gère le dossier `blog/`. 54 | -------------------------------------------------------------------------------- /blog/index.php: -------------------------------------------------------------------------------- 1 | 0) { 17 | $identifier = $_GET['id']; 18 | 19 | (new Post())->execute($identifier); 20 | } else { 21 | throw new Exception('Aucun identifiant de billet envoyé'); 22 | } 23 | } elseif ($_GET['action'] === 'addComment') { 24 | if (isset($_GET['id']) && $_GET['id'] > 0) { 25 | $identifier = $_GET['id']; 26 | 27 | (new AddComment())->execute($identifier, $_POST); 28 | } else { 29 | throw new Exception('Aucun identifiant de billet envoyé'); 30 | } 31 | } elseif ($_GET['action'] === 'updateComment') { 32 | if (isset($_GET['id']) && $_GET['id'] > 0) { 33 | $identifier = $_GET['id']; 34 | // It sets the input only when the HTTP method is POST (ie. the form is submitted). 35 | $input = null; 36 | if ($_SERVER['REQUEST_METHOD'] === 'POST') { 37 | $input = $_POST; 38 | } 39 | 40 | (new UpdateComment())->execute($identifier, $input); 41 | } else { 42 | throw new Exception('Aucun identifiant de commentaire envoyé'); 43 | } 44 | } else { 45 | throw new Exception("La page que vous recherchez n'existe pas."); 46 | } 47 | } else { 48 | (new Homepage())->execute(); 49 | } 50 | } catch (Exception $e) { 51 | $errorMessage = $e->getMessage(); 52 | 53 | require('templates/error.php'); 54 | } 55 | -------------------------------------------------------------------------------- /blog/src/controllers/comment/add.php: -------------------------------------------------------------------------------- 1 | connection = new DatabaseConnection(); 26 | $success = $commentRepository->createComment($post, $author, $comment); 27 | if (!$success) { 28 | throw new \Exception('Impossible d\'ajouter le commentaire !'); 29 | } else { 30 | header('Location: index.php?action=post&id=' . $post); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /blog/src/controllers/comment/update.php: -------------------------------------------------------------------------------- 1 | connection = new DatabaseConnection(); 28 | $success = $commentRepository->updateComment($identifier, $author, $comment); 29 | if (!$success) { 30 | throw new \Exception('Impossible de modifier le commentaire !'); 31 | } else { 32 | header('Location: index.php?action=updateComment&id=' . $identifier); 33 | } 34 | } 35 | 36 | // Otherwise, it displays the form. 37 | $commentRepository = new CommentRepository(); 38 | $commentRepository->connection = new DatabaseConnection(); 39 | $comment = $commentRepository->getComment($identifier); 40 | if ($comment === null) { 41 | throw new \Exception("Le commentaire $identifier n'existe pas."); 42 | } 43 | 44 | require('templates/update_comment.php'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /blog/src/controllers/homepage.php: -------------------------------------------------------------------------------- 1 | connection = new DatabaseConnection(); 17 | $posts = $postRepository->getPosts(); 18 | 19 | require('templates/homepage.php'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /blog/src/controllers/post.php: -------------------------------------------------------------------------------- 1 | connection = $connection; 21 | $post = $postRepository->getPost($identifier); 22 | 23 | $commentRepository = new CommentRepository(); 24 | $commentRepository->connection = $connection; 25 | $comments = $commentRepository->getComments($identifier); 26 | 27 | require('templates/post.php'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /blog/src/lib/database.php: -------------------------------------------------------------------------------- 1 | database === null) { 12 | $this->database = new \PDO('mysql:host=localhost;dbname=blog;charset=utf8', 'blog', 'password'); 13 | } 14 | 15 | return $this->database; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /blog/src/model/comment.php: -------------------------------------------------------------------------------- 1 | connection->getConnection()->prepare( 25 | "SELECT id, author, comment, DATE_FORMAT(comment_date, '%d/%m/%Y à %Hh%imin%ss') AS french_creation_date, post_id FROM comments WHERE post_id = ? ORDER BY comment_date DESC" 26 | ); 27 | $statement->execute([$post]); 28 | 29 | $comments = []; 30 | while (($row = $statement->fetch())) { 31 | $comment = new Comment(); 32 | $comment->identifier = $row['id']; 33 | $comment->author = $row['author']; 34 | $comment->frenchCreationDate = $row['french_creation_date']; 35 | $comment->comment = $row['comment']; 36 | $comment->post = $row['post_id']; 37 | 38 | $comments[] = $comment; 39 | } 40 | 41 | return $comments; 42 | } 43 | 44 | public function getComment(string $identifier): ?Comment 45 | { 46 | $statement = $this->connection->getConnection()->prepare( 47 | "SELECT id, author, comment, DATE_FORMAT(comment_date, '%d/%m/%Y à %Hh%imin%ss') AS french_creation_date, post_id FROM comments WHERE id = ?" 48 | ); 49 | $statement->execute([$identifier]); 50 | 51 | $row = $statement->fetch(); 52 | if ($row === false) { 53 | return null; 54 | } 55 | 56 | $comment = new Comment(); 57 | $comment->identifier = $row['id']; 58 | $comment->author = $row['author']; 59 | $comment->frenchCreationDate = $row['french_creation_date']; 60 | $comment->comment = $row['comment']; 61 | $comment->post = $row['post_id']; 62 | 63 | return $comment; 64 | } 65 | 66 | public function createComment(string $post, string $author, string $comment): bool 67 | { 68 | $statement = $this->connection->getConnection()->prepare( 69 | 'INSERT INTO comments(post_id, author, comment, comment_date) VALUES(?, ?, ?, NOW())' 70 | ); 71 | $affectedLines = $statement->execute([$post, $author, $comment]); 72 | 73 | return ($affectedLines > 0); 74 | } 75 | 76 | public function updateComment(string $identifier, string $author, string $comment): bool 77 | { 78 | $statement = $this->connection->getConnection()->prepare( 79 | 'UPDATE comments SET author = ?, comment = ? WHERE id = ?' 80 | ); 81 | $affectedLines = $statement->execute([$author, $comment, $identifier]); 82 | 83 | return ($affectedLines > 0); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /blog/src/model/post.php: -------------------------------------------------------------------------------- 1 | connection->getConnection()->prepare( 24 | "SELECT id, title, content, DATE_FORMAT(creation_date, '%d/%m/%Y à %Hh%imin%ss') AS french_creation_date FROM posts WHERE id = ?" 25 | ); 26 | $statement->execute([$identifier]); 27 | 28 | $row = $statement->fetch(); 29 | $post = new Post(); 30 | $post->title = $row['title']; 31 | $post->frenchCreationDate = $row['french_creation_date']; 32 | $post->content = $row['content']; 33 | $post->identifier = $row['id']; 34 | 35 | return $post; 36 | } 37 | 38 | public function getPosts(): array 39 | { 40 | $statement = $this->connection->getConnection()->query( 41 | "SELECT id, title, content, DATE_FORMAT(creation_date, '%d/%m/%Y à %Hh%imin%ss') AS french_creation_date FROM posts ORDER BY creation_date DESC LIMIT 0, 5" 42 | ); 43 | $posts = []; 44 | while (($row = $statement->fetch())) { 45 | $post = new Post(); 46 | $post->title = $row['title']; 47 | $post->frenchCreationDate = $row['french_creation_date']; 48 | $post->content = $row['content']; 49 | $post->identifier = $row['id']; 50 | 51 | $posts[] = $post; 52 | } 53 | 54 | return $posts; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /blog/style.css: -------------------------------------------------------------------------------- 1 | h1, h3 2 | { 3 | text-align:center; 4 | } 5 | h3 6 | { 7 | background-color:black; 8 | color:white; 9 | font-size:0.9em; 10 | margin-bottom:0px; 11 | } 12 | .news p 13 | { 14 | background-color:#CCCCCC; 15 | margin-top:0px; 16 | } 17 | .news 18 | { 19 | width:70%; 20 | margin:auto; 21 | } 22 | 23 | a 24 | { 25 | text-decoration: none; 26 | color: blue; 27 | } 28 | -------------------------------------------------------------------------------- /blog/templates/error.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Le super blog de l'AVBN !

5 |

Une erreur est survenue :

6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /blog/templates/homepage.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Le super blog de l'AVBN !

5 |

Derniers billets du blog :

6 | 7 | 10 |
11 |

12 | title); ?> 13 | le frenchCreationDate; ?> 14 |

15 |

16 | content)); ?> 17 |
18 | Commentaires 19 |

20 |
21 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /blog/templates/layout.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <?= $title ?> 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /blog/templates/post.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Le super blog de l'AVBN !

5 |

Retour à la liste des billets

6 | 7 |
8 |

9 | title) ?> 10 | le frenchCreationDate ?> 11 |

12 | 13 |

14 | content)) ?> 15 |

16 |
17 | 18 |

Commentaires

19 | 20 |
21 |
22 |
23 | 24 |
25 |
26 |
27 | 28 |
29 |
30 | 31 |
32 |
33 | 34 | 37 |

author) ?> le frenchCreationDate ?> (modifier)

38 |

comment)) ?>

39 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /blog/templates/update_comment.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Le super blog de l'AVBN !

5 |

Retour au billet

6 | 7 |

Modification du commentaire

8 | 9 |
10 |
11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 |
19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /db.sql: -------------------------------------------------------------------------------- 1 | -- Ce fichier sert à initialiser la base de données 2 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 3 | SET time_zone = "+00:00"; 4 | 5 | CREATE TABLE `posts` ( 6 | `id` int(11) NOT NULL, 7 | `title` varchar(255) NOT NULL, 8 | `content` text NOT NULL, 9 | `creation_date` datetime NOT NULL 10 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 11 | 12 | INSERT INTO `posts` (`id`, `title`, `content`, `creation_date`) VALUES 13 | (1, 'Bienvenue sur le blog de l\'AVBN !', 'Je vous souhaite à toutes et à tous la bienvenue sur le blog qui parlera de... l\'Association de VolleyBall de Nuelly !', '2022-02-17 16:28:41'), 14 | (2, 'L\'AVBN à la conquête du monde !', 'C\'est officiel, le club a annoncé à la radio hier soir \"J\'ai l\'intention de conquérir le monde !\".\r\nIl a en outre précisé que le monde serait à sa botte en moins de temps qu\'il n\'en fallait pour dire \"Association de VolleyBall de Nuelly\". Pas dur, ceci dit entre nous...', '2022-02-17 16:28:42'); 15 | 16 | ALTER TABLE `posts` 17 | ADD PRIMARY KEY (`id`); 18 | 19 | ALTER TABLE `posts` 20 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; 21 | 22 | CREATE TABLE `comments` ( 23 | `id` int (11) NOT NULL, 24 | `post_id` INT (11) NOT NULL, 25 | `author` varchar(255) NOT NULL, 26 | `comment` text NOT NULL, 27 | `comment_date` datetime NOT NULL 28 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 29 | 30 | INSERT INTO `comments` (`id`, `post_id`, `author`, `comment`, `comment_date`) VALUES 31 | (1, 1, 'Mathieu', 'Preum\'s', '2022-03-03 13:00:42'), 32 | (2, 1, 'Sam', 'Quelqu\'un a un avis là-dessus ? Je ne sais pas quoi en penser.', '2022-03-03 13:01:42'); 33 | 34 | ALTER TABLE `comments` 35 | ADD PRIMARY KEY (`id`); 36 | 37 | ALTER TABLE `comments` 38 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3 39 | --------------------------------------------------------------------------------