• 10 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

Ce cours existe en livre papier.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 14/06/2024

Structurez vos fichiers

Maintenant que nous avons le moyen d’identifier des classes par leur espace de noms, et que cet espace peut représenter une arborescence de répertoires, nous allons structurer et distribuer nos fichiers en suivant cette règle.

On va se fixer une règle supplémentaire : un fichier pour une classe. À chaque appel de classe on va charger le fichier associé. Non seulement cela diminue la taille de vos fichiers, mais en prime PHP n’ira charger et analyser que le strict nécessaire au moment de la requête. :D

Voyons à quoi cette distribution peut ressembler avec l'exemple des messages du chapitre précédent. Le fichier index.php :

<?php

require_once('Domain/Forum/Message.php');

$forumMessage = new Domain\Forum\Message;

var_dump(get_class($forumMessage));

Notre classe Message a son propre fichier  Message.php  dans le dossierForum; lui-même à un l'intérieur du dossierDomain. Volontairement, je reste dans la simplicité.

Voici le code de notre fichier  Message.php  : 

<?php

declare(strict_types=1);

namespace Domain\Forum;

class Message
{

}

Capture d'écran avec le résultat du run à partir du code précédent
Le résultat lorsqu'on lance le run

Mais à présent, ajoutons une classe  utilisateur dédiée pour définir l'auteur du message.

Voyons ce que ça donne, pour le fichierindex.php  :

<?php

require_once('Domain/Forum/Message.php');
require_once('Domain/User/User.php');

use Domain\Forum\Message;
use Domain\User\User;

$user = new User;
$user->name = 'Greg';

$forumMessage = new Message($user, 'J\'aime les pates.');

var_dump($forumMessage);

Notre classe  User  a son propre fichier   User.php  dans le dossier  User  ; lui-même rangé à l'intérieur du dossier  Domain  :

<?php

declare(strict_types=1);

namespace Domain\User;

class User
{
    public $name;
}

Capture d'écran avec le résultat du run à partir du code précédent
Le résultat lorsqu'on lance le run

Regardons ça de plus près dans le screencast ci-dessous :

Nous sommes obligés d’utiliser require_once  pour chaque fichier de chaque classe utilisée... Ça veut dire que pour toutes les classes que j'utilise potentiellement, je suis obligé de faire cet import de fichier. Même si l'utilisation de la classe est dans une condition IF et que la classe n'est pas utilisée systématiquement

C'est pourquoi nous allons utiliser une technique grâce à une bibliothèque fournie avec PHP : le chargement automatisé de la bibliothèque standard PHP, SPL.

Tirez profit du chargement automatisé

Dans la bibliothèque SPL se trouve une fonction nommée   spl_autoload_register. Suivez-moi dans le screencast juste en dessous pour un premier aperçu de cette mécanique :

Lorsque vous tentez de charger une classe (instanciation, usage de constante, etc.) alors que PHP ne la trouve pas, PHP va appeler automatiquement les fonctions enregistrées précédemment à l’aide de  spl_autoload_register. À la suite de l’exécution des fonctions enregistrées, le script reprend son cours et tente à nouveau de charger la classe. Si le script échoue à nouveau, il s'arrête.

S'il y a un échec de chargement après une tentative de charger une classe dans un fichier PHP, on peut faire appel à la fonction spl_autoload_register. Cela déclenchera une nouvelle tentative d'enregistrement. Si la classe est disponible, le script co
Le chargement automatisé

Puisque nous écrivons nos espaces de noms comme des chemins de répertoire, si notre arborescence de fichier correspond, alors on peut automatiser le chargement des fichiers :

<?php

spl_autoload_register(static function(string $fqcn) {
   // $fqcn contient Domain\Forum\Message
   // remplaçons les \ par des / et ajoutons .php à la fin.
   // on obtient Domain/Forum/Message.php
   $path = str_replace('\\', '/', $fqcn).'.php';

   // puis chargeons le fichier
   require_once($path);
});

use Domain\Forum\Message;

$forumMessage = new Message;

Tester ce code

Ici, nous disons à PHP : “Si tu n’arrives pas à charger une classe, voici la fonction que tu peux exécuter pour tenter de la trouver”. La fonction en question débute à la fin de la ligne 3 et fait un require_once de la classe à partir de son nom complet. Il se trouve que cette façon de faire est la méthode par défaut dans PHP. On aurait pu se contenter d'écrire : 

spl_autoload_register();

Cette façon de répartir son code en fichiers et répertoires, et d'accorder les espaces de noms, est d'ailleurs très bien détaillée la recommandation standard de PHP PSR-4 (en anglais).

Eh bien, grâce à cette technique, les classes et donc les fichiers sont chargés uniquement lorsque c'est nécessaire ! Moins à parser, et moins à interpréter, donc de meilleures performances et moins de consommation de mémoire ! Des fichiers plus petits donc plus simples et moins susceptibles de contenir des erreurs ou des bugs ! Que demande le peuple ? Du code maintenable et évolutif ? OK OK on y va !

Exercez-vous

Il est temps de pratiquer. Utilisez la fonction   spl_autoload_register  pour charger automatiquement vos classes, et répartissez-les dans une arborescence correspondant à vos espaces de noms afin de respecter PSR-4.

‌Vous trouverez le code sur la branche P3C2, et la correction sur la branche P3C2-correction

En résumé

  • Les espaces de noms peuvent être utilisés pour correspondre à l'arborescence des fichiers, dans le but d'importer ces fichiers dynamiquement (PSR-4).

  • Utiliser SPL combiné aux espaces de noms permet de charger les classes à la volée.

  • Séparer les classes par fichiers réduit le nombre de fichiers à charger et à interpréter pour le langage.

Maintenant que nous avons un moyen de facilement gérer et distribuer nos classes dans notre système de fichiers, ce sera plus facile pour la suite. :) Regardons ensemble des concepts un peu plus avancés de l'héritage dans le prochain chapitre !

Exemple de certificat de réussite
Exemple de certificat de réussite