Dans notre grand combat pour la propreté du code, nous pouvons aller plus loin (spoiler : nous pouvons toujours aller plus loin). Il va bien falloir s'arrêter quelque part, et on s'approche du but que je m'étais fixé : vous aider à structurer votre code en MVC.
Il y a quand même un nouveau concept que j'aimerais vous présenter...
Découvrez le rôle des namespaces
De quoi va-t-on parler aujourd'hui ? Des espaces de nom (namespaces). Leur rôle ? Éviter les collisions de noms de classes.
Imaginez. Vous travaillez sur un gros programme. Vous réutilisez plusieurs bibliothèques. Vous pouvez être sûr qu'à un moment donné, il va bien y avoir quelqu'un qui a eu l'idée saugrenue de créer une classe CommentRepository
ouPostRepository
tout comme vous ! À ce moment-là, c'est le plantage garanti : on n'a pas le droit d'appeler deux classes par le même nom…
… sauf si on utilise les namespaces bien sûr ! Ils agissent un peu comme des dossiers. Ils vous permettent d'avoir 2 classes du même nom dans votre programme, du moment qu'elles sont dans des namespaces différents.
Mettez en place votre premier namespace
Concrètement, les namespaces ont cette forme :
Entreprise\Projet\Section
Ce sont vraiment comme des dossiers. D'ailleurs, il est recommandé d'utiliser l'arborescence des dossiers pour construire celle de l'espace de nom. Vous pouvez en imbriquer autant que vous voulez :
Entreprise\Projet\Section\SousSection\SousSousSection
Pour définir un namespace, rien de plus simple. On va déclarer unnamespace
juste avant la définition de la classe :
<?php
namespace Application\Model\Post;
require_once('src/lib/database.php');
// ...
class PostRepository
{
public \DatabaseConnection $connection;
// ...
}
Cela a un impact : les noms complets de toutes les classes et fonctions déclarées dans ce fichier sont désormais différents ! Ils sont le résultat de la concaténation de l'espace de nom avec leur nom interne.
Ça veut dire que je vais devoir repasser sur tous mes fichiers pour renseigner le nouveau nom ?
Exactement ! Tous les fichiers qui font appel aux classes de ce fichier doivent maintenant ajouter le namespace en préfixe. Voilà par exemple à quoi va ressembler votre contrôleursrc/controllers/post.php
:
<?php
require_once('src/lib/database.php');
require_once('src/model/comment.php');
require_once('src/model/post.php');
function post(string $identifier)
{
$connection = new DatabaseConnection();
$postRepository = new \Application\Model\Post\PostRepository();
$postRepository->connection = $connection;
$post = $postRepository->getPost($identifier);
$commentRepository = new CommentRepository();
$commentRepository->connection = $connection;
$comments = $commentRepository->getComments($identifier);
require('templates/post.php');
}
Évitez la répétition du préfixe
Hum, ça me paraît quand même plus long à écrire tout ça. N'y a-t-il pas moyen d'éviter de répéter le namespace en préfixe à chaque fois ?
Oui, c'est possible. Il faut utiliser le mot-clé use
en début d'un fichier qui fait régulièrement appel à des classes d'un même namespace :
<?php
require_once('src/lib/database.php');
require_once('src/model/comment.php');
require_once('src/model/post.php');
use Application\Model\Post\PostRepository;
function post(string $identifier)
{
$connection = new DatabaseConnection();
$postRepository = new PostRepository();
$postRepository->connection = $connection;
$post = $postRepository->getPost($identifier);
$commentRepository = new CommentRepository();
$commentRepository->connection = $connection;
$comments = $commentRepository->getComments($identifier);
require('templates/post.php');
}
D'ailleurs, la plupart du code que vous pourrez croiser dans le milieu professionnel utilise toujours cesuse
. C'est une manière de construire un index des dépendances de votre fichier.
Récapitulons en vidéo
Exercez-vous
L'exercice pour ce chapitre sera simple à expliquer : mettez tout le code situé dans le dossiersrc/
dans des espaces de noms ! Ça va faire beaucoup de petites modifications et vous devrez vérifier que toutes les fonctionnalités de votre blog restent fonctionnelles.
Pour le code de vos contrôleurs, vous avez le choix : refactoriser vos contrôleurs en objets ou les laisser en fonctions. Je vous recommande la première option. Cependant, si vous prenez la seconde, sachez que le mot-cléuse function
existe. 😁
En résumé
Un espace de nom, ou namespace, est un "dossier virtuel" dans lequel ranger : des classes, des fonctions et d'autres espaces de nom. Il se renseigne en haut du fichier, avant toute déclaration de classe ou de fonction, avec le mot-clé
namespace
.Une arborescence d'espaces de nom permet de segmenter ses classes et fonctions de la même façon qu'une arborescence de dossiers permet de segmenter ses fichiers.
Une fois qu'une classe ou fonction est rangée dans un espace de nom, on doit y accéder par son chemin complet par le code situé dans un autre espace de nom. Le code situé dans le même espace de nom peut toujours utiliser les noms sans le préfixe.
Le mot-clé
use
peut être utilisé pour pré-définir un nom au sein d'un fichier. Le cas le plus habituel est de s'en servir pour enlever le préfixe.
C'est super, on dispose d'un nouvel outil pour segmenter notre code ! On n'a enfin plus l'obligation de connaître toutes les classes et les fonctions du projet pour être sûr de ne pas créer de conflit.
Bien sûr, ça alourdit légèrement le code... Pour compenser, dans le dernier chapitre, je vous présenterai rapidement une notion un peu complexe, mais utilisée sur presque 100 % des projets : l'autoloading. Associée aux espaces de nom, vous n'aurez plus jamais besoin de vos `require_once`, c'est génial ! Mais d'abord, embarquons pour le prochain chapitre : vous allez coder !