7. L'architecture et les namespaces

Il est temps de mettre en place une architecture pour être mieux organisé, avec un code plus facile à maintenir et à faire évoluer.

Mettons en place le modèle MVC !

 

Refactorisons notre application : étape 1

Nous allons commencer par mettre en place une architecture plus adaptée.

Mais on en a déjà une en place, elle n'est pas bien ? 😒

Nous devons mettre en place une architecture professionnelle, et l'actuelle risque d'être très limite.
Nous allons créer l'architecture suivante :
- un dossier  config  à la racine de notre projet, qui contiendra la configuration de notre application;

- un dossier  public  , qui sera le seul dossier accessible à l'utilisateur final, avec un dossier  css  à l'intérieur, ainsi qu'un dossier js  ,  fonts  et  img

- un dossier  src  qui contiendra toute notre logique, où on retrouver les dossiers   model  (contenant les classes), un dossier  controller  (pour les contrôleurs) et un dossier  DAO  (pour les managers).

- un dossier  templates  qui contiendra nos vues.

 

Nous allons mettre les fichiers  Article.php  ,  Comment.php  et  Database.php  dans le dossier  DAO .

On place  home.php  et  single.php  dans le dossier  templates

Voici la nouvelle architecture :


 

Plus rien ne marche ! 😱😱😱

Calmez-vous, on va remédier à ceci dès maintenant.

 

Refactorisons notre application : étape 2

Nous allons commencer par renommer nos classes  Database  ,  Article  et  Comment  :
- on renomme  Database  en  DAO  
- on renomme  Article  en  ArticleDAO  
- on renomme  Comment  en  CommentDAO

Pensez à changer le nom de la classe et le nom du fichier 😁

On va aussi modifier l'appel à nos fichiers sur  home.php  et  single.php  : 

<?php
//Pour nos deux fichiers
require '../src/DAO/DAO.php';
require '../src/DAO/ArticleDAO.php';
//Uniquement pour single.php
require '../src/DAO/CommentDAO.php';

Vous voyez que la refactorisation ne fait pas de mal 😛

Si vous essayez d'accéder à la page  home.php  ,  dans le dossier  templates  , l'affichage fonctionne correctement. Le lien vers le fichier  single.php  fonctionne très bien aussi.

Pensez à bien accéder à l'URL suivante : http://localhost/blog/templates/home.php (nos fichiers sont dans le dossier templates maintenant).

 

Utilisons les namespaces

Mais pourquoi ? Moi je n'ai pas envie de les utiliser ! 😠

Je sais. Mais dans le cas où votre projet évoluerait et que l'on pourrait être susceptible d'ajouter des librairies externes, il faut s'assurer que nos classes ne rentrent pas en conflit avec d'autres.

Il y a ici peu de choses à modifier 😉

Ajouter dans vos fichiers  DAO.php  ,  ArticleDAO.php  et  CommentDAO.php  la ligne suivante (avant la déclaration de la classe). Pour la classe DAO en particulier, ajoutez aussi la ligne indiquée :

<?php

//Pour toutes les classes dans DAO
namespace App\src\DAO;

//Uniquement pour la classe DAO
use PDO;
use Exception;

Du côté  des templates, vous devez modifier légèrement vos appels aux classes comme ici pour  home.php  :

<?php
require '../src/DAO/DAO.php';
require '../src/DAO/ArticleDAO.php';
?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="utf-8">
    <title>Mon blog</title>
</head>

<body>
<div>
    <h1>Mon blog</h1>
    <p>En construction</p>
    <?php
    $article = new \App\src\DAO\ArticleDAO();
    $articles = $article->getArticles();
    while($article = $articles->fetch())
    {
        ?>
        <div>
            <h2><a href="single.php?articleId=<?= htmlspecialchars($article->id);?>"><?= htmlspecialchars($article->title);?></a></h2>
            <p><?= htmlspecialchars($article->content);?></p>
            <p><?= htmlspecialchars($article->author);?></p>
            <p>Créé le : <?= htmlspecialchars($article->createdAt);?></p>
        </div>
        <br>
        <?php
    }
    $articles->closeCursor();
    ?>
</div>
</body>
</html>

Et pour  single.php  :

<?php
require '../src/DAO/DAO.php';
require '../src/DAO/ArticleDAO.php';
require '../src/DAO/CommentDAO.php';
?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="utf-8">
    <title>Mon blog</title>
</head>

<body>
<div>
    <h1>Mon blog</h1>
    <p>En construction</p>
    <?php
    $article = new \App\src\DAO\ArticleDAO();
    $articles = $article->getArticle($_GET['articleId']);
    $article = $articles->fetch()
    ?>
    <div>
        <h2><?= htmlspecialchars($article->title);?></h2>
        <p><?= htmlspecialchars($article->content);?></p>
        <p><?= htmlspecialchars($article->author);?></p>
        <p>Créé le : <?= htmlspecialchars($article->createdAt);?></p>
    </div>
    <br>
    <?php
    $articles->closeCursor();
    ?>
    <a href="home.php">Retour à l'accueil</a>
    <div id="comments" class="text-left" style="margin-left: 50px">
        <h3>Commentaires</h3>
        <?php
        $comment = new \App\src\DAO\CommentDAO();
        $comments = $comment->getCommentsFromArticle($_GET['articleId']);
        while($comment = $comments->fetch())
        {
            ?>
            <h4><?= htmlspecialchars($comment->pseudo);?></h4>
            <p><?= htmlspecialchars($comment->content);?></p>
            <p>Posté le <?= htmlspecialchars($comment->createdAt);?></p>
            <?php
        }
        $comments->closeCursor();
        ?>
    </div>
</div>
</body>
</html>

Si vous actualisez votre navigateur, cela fonctionne toujours très bien 😉

Maintenant que nous avons mis en place les namespaces, essayons de les utiliser correctement en simplifiant le nom de la classe lors de l'instanciation et en utilisant la directive use au besoin. 

Voici le fichier home.php actualisé : 

<?php
require '../src/DAO/DAO.php';
require '../src/DAO/ArticleDAO.php';

use App\src\DAO\ArticleDAO;
?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="utf-8">
    <title>Mon blog</title>
</head>

<body>
<div>
    <h1>Mon blog</h1>
    <p>En construction</p>
    <?php
    $article = new ArticleDAO();
    $articles = $article->getArticles();
    while($article = $articles->fetch())
    {
        ?>
        <div>
            <h2><a href="single.php?articleId=<?= htmlspecialchars($article->id);?>"><?= htmlspecialchars($article->title);?></a></h2>
            <p><?= htmlspecialchars($article->content);?></p>
            <p><?= htmlspecialchars($article->author);?></p>
            <p>Créé le : <?= htmlspecialchars($article->createdAt);?></p>
        </div>
        <br>
        <?php
    }
    $articles->closeCursor();
    ?>
</div>
</body>
</html>

Et le fichier single.php :

<?php
require '../src/DAO/DAO.php';
require '../src/DAO/ArticleDAO.php';
require '../src/DAO/CommentDAO.php';

use App\src\DAO\ArticleDAO;
use App\src\DAO\CommentDAO;
?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="utf-8">
    <title>Mon blog</title>
</head>

<body>
<div>
    <h1>Mon blog</h1>
    <p>En construction</p>
    <?php
    $article = new ArticleDAO();
    $articles = $article->getArticle($_GET['articleId']);
    $article = $articles->fetch()
    ?>
    <div>
        <h2><?= htmlspecialchars($article->title);?></h2>
        <p><?= htmlspecialchars($article->content);?></p>
        <p><?= htmlspecialchars($article->author);?></p>
        <p>Créé le : <?= htmlspecialchars($article->createdAt);?></p>
    </div>
    <br>
    <?php
    $articles->closeCursor();
    ?>
    <a href="home.php">Retour à l'accueil</a>
    <div id="comments" class="text-left" style="margin-left: 50px">
        <h3>Commentaires</h3>
        <?php
        $comment = new CommentDAO();
        $comments = $comment->getCommentsFromArticle($_GET['articleId']);
        while($comment = $comments->fetch())
        {
            ?>
            <h4><?= htmlspecialchars($comment->pseudo);?></h4>
            <p><?= htmlspecialchars($comment->content);?></p>
            <p>Posté le <?= htmlspecialchars($comment->createdAt);?></p>
            <?php
        }
        $comments->closeCursor();
        ?>
    </div>
</div>
</body>
</html>
Oui mais attends, c'est bien de faire des require, mais c'est répétitif, et si on en oublie un ? 😌

Bon d'accord, je vous l'accorde, ce n'est pas idéal, nous allons mettre en place un autoloader pour y remédier.

 

Quelques révisions

Si vous avez besoin de revoir certains points, voici les liens en conséquence :

Namespaces

 

Bilan

Dans ce chapitre, nous avons mis en place une architecture MVC qui va nous servir pour la suite pour mieux organiser notre code. Nous en avons profité pour ajouter les namespaces à nos DAO pour faciliter l'intégration d'un Autoloader.

Vous pouvez retrouver le code associé à ce chapitre sur GitHub.