A free and open-source book on ZF3 for beginners

Translation into this language is not yet finished. You can help this project by translating the chapters and contributing your changes.

3.4. Chargement automatique des classes PHP

Une application se compose de nombreuses classes PHP et chaque classe réside généralement dans un fichier distinct. Cela introduit le besoin d'inclure les fichiers.

Par exemple, supposons que nous ayons le fichier Application.php qui contient la définition de la classe \Zend\Mvc\Application de la section précédente. Avant de pouvoir créer une instance de la classe Application quelque part dans votre code, vous devez inclure le contenu du fichier Application.php (vous pouvez le faire à l'aide de l'instruction require_once en lui passant le chemin d'accès complet au fichier) :

<?php
require_once "/path/to/zendframework/zend-mvc/src/Application.php";

use Zend\Mvc\Application;

$application = new Application();

Au fur et à mesure que votre application augmente en taille, il peut être difficile d'inclure chaque fichier nécessaire. Zend Framework 3 lui-même se compose de centaines de fichiers, et il peut être très difficile de charger la bibliothèque entière et toutes ses dépendances de cette façon. De plus, lors de l'exécution du code résultant, l'interpréteur PHP prendra du temps CPU pour traiter chaque fichier inclus, même si vous ne créez pas une instance de ladite classe.

Pour résoudre ce problème, en PHP, une fonctionnalité de chargement automatique de classe a été introduite. La fonction PHP spl_autoload_register() vous permet de créer une fonction d'autoloading (chargement automatique). Pour les sites complexes, vous pouvez même créer plusieurs fonctions de chargement automatique, qui sont chaînées dans une pile.

Pendant l'exécution du script, si l'interpréteur PHP rencontre un nom de classe qui n'a pas encore été défini, il appelle la ou les autoloaders déclarées jusqu'à ce qu'il y en est un qui trouve la classe ou que l'erreur "not found" soit levée. Cela permet un chargement "lazy" (paresseux), l'interpréteur PHP ne traite la définition de la classe qu'au moment de l'appel de cette classe, ie, quand cela est vraiment nécessaire.

3.4.1. Mapping d'une classe Autoloader

Pour vous donner une idée de la façon dont une fonction d'autoloading se présente, voyons ci-dessous une implémentation simplifiée d'une fonction d'autoloading :

<?php
// Autoloader function.
function autoloadFunc($className)
{
    // Mappage des classes dans un tableau statique.
    static $classMap = [
        '\\Zend\\Mvc\\Application' => '/path/to/zendframework/zend-mvc/src/Zend/Mvc/Application.php',
        '\\Application\\Module' => '/path/to/app/dir/module/Application/Module.php',
        //...
    ];

    // Vérifie si un tel nom de classe est présent dans la class map.
    if(isset(static::$classMap[$className])) {
        $fileName = static::$classMap[$className];

        // Vérifie si le fichier existe et est lisible.
        if (is_readable($fileName)) {
            // Inclus le fichier.
            require $fileName;
        }
    }
}

// Déclaration de la function d'autoloading
spl_autoload_register("autoloadFunc");

Dans l'exemple ci-dessus, nous définissons la fonction de chargement automatique autoloadFunc() que nous désignerons sous le nom de class map d'autoloader.

L'autoloader de class map utilise le mappage de classe pour mapper le nom de classe et le chemin absolu vers le fichier PHP contenant cette classe. La class map est juste un tableau PHP contenant des clés et des valeurs. Pour déterminer le chemin d'accès au fichier par nom de classe, l'autoloader de la classe doit simplement extraire la valeur du tableau de class map. Il est évident que l'autoloader de class map fonctionne très vite. Cependant, le désavantage est que vous devez maintenir la class map et la mettre à jour à chaque fois que vous ajoutez une nouvelle classe à votre programme.

3.4.2. La Norme PSR-4

Comme chaque fournisseur de bibliothèque utilise ses propres conventions de nommage et d'organisation de fichier, vous devrez enregistrer une fonction de chargement automatique personnalisée différente pour chaque bibliothèque dépendante, ce qui est plutôt ennuyeux. Pour résoudre ce problème, la norme PSR-4 a été introduite.

PSR signifie PHP Standards Recommendation.

La norme PSR-4 définit la structure de code recommandée qu'une application ou une bibliothèque doit suivre pour garantir l'interopérabilité de l'autoloader. En deux mots, la norme dit que :

Par exemple, pour la classe Zend\Mvc\Application, vous aurez la structure de répertoire suivante :

/path/to/zendframework/zend-mvc/src
  /Zend
    /Mvc
       Application.php

L'inconvénient de ceci est que vous devez mettre votre code dans plusieurs répertoires imbriqués (Zend et Mvc).

Pour résoudre ce problème, le PSR-4 vous permet de définir une série contiguë d'un ou plusieurs namespaces et sous-namespaces correspondants à un "répertoire de base". Par exemple, si vous avez le nom de classe complet \Zend\Mvc\Application, et si vous définissez que \Zend\Mvc correspond au répertoire "/path/to/zendframework/zend-mvc/src", vous pouvez organisez vos fichiers comme suit:

/path/to/zendframework/zend-mvc/src
    Application.php

Pour le code soit conforme à la norme PSR-4, nous pouvons écrire et déclarer un autoloader, que nous appellerons l'autoloader "standard" :

<?php

// Fonction de chargement automatique "Standard".
function standardAutoloadFunc($className)
{
    // Remplace le préfixe du namespace par le répertoire de base.
    $prefix = '\\Zend\\Mvc';
    $baseDir = '/path/to/zendframework/zend-mvc/src/';
    if (substr($className, 0, strlen($prefix)) == $prefix) {
        $className = substr($className, strlen($prefix)+1);
        $className = $baseDir . $className;
    }

    // Remplace les séparateurs d'espace de noms dans le namespace par des séparateurs de répertoire.
    $className = str_replace('\\', DIRECTORY_SEPARATOR, $className);

    // Ajoute l'extension .php.
    $fileName = $className . ".php";

    // Vérifie si le fichier existe et est lisible.
    if (is_readable($fileName)) {
        // Inclus  le fichier.
        require $fileName;
    }
}

// Déclaration de la fonction d'autoloader.
spl_autoload_register("standardAutoloadFunc");

L'autoloader standard fonctionne comme suit. En supposant que le namespace des classes peut être mappé à la structure des répertoires un par un, la fonction calcule le chemin vers le fichier PHP en transformant les back-slashes (séparateurs de namespace) en forward slashes (séparateurs de chemin) et en concaténant le chemin d'accès absolu au dossier où se trouve la bibliothèque. Ensuite, la fonction vérifie si un tel fichier PHP existe vraiment, et si oui, l'inclut avec l'instruction require.

Il est évident que l'autoloader standard fonctionne plus lentement que l'autoloader de class map. Cependant, son avantage est que vous n'avez pas besoin de gérer une class map, ce qui est très pratique lorsque vous développez un nouveau code et ajoutez de nouvelles classes à votre application.

Zend Framework 3 est conforme à la norme PSR-4, ce qui permet d'utiliser un mécanisme d'autoloading standard sur tous ses composants. Il est également compatible avec d'autres librairies conformes au PSR-4 comme Doctrine ou Symfony.

3.4.3. L'Autoloader fournis par Composer

Composer peut générer des fonctions d'autoloading (à la fois des autoloaders de class map et des autoloader norme PSR-4) pour le code que vous installez avec. Zend Framework 3 utilise l'autoloader fournie par Composer. Lorsque vous installez un package avec Composer, il crée automatiquement le fichier APP_DIR/vendor/autoload.php, qui utilise la fonction PHP spl_autoload_register() pour déclarer un autoloader. De cette façon, toutes les classes PHP situées dans le répertoire APP_DIR/vendor sont chargées automatiquement.

Pour charger automatiquement les classes PHP situées dans vos propres modules (comme le module Application), vous devez spécifier la clé autoload dans votre fichier composer.json :

"autoload": {
    "psr-4": {
        "Application\\": "module/Application/src/"
    }
},

Ensuite, la seule chose à faire est d'inclure ce fichier dans votre script d'entrée index.php :

// Composer autoloading
include __DIR__ . '/../vendor/autoload.php';

Le fichier autoload.php est généré chaque fois que vous installez un package avec Composer. Au besoin, pour que Composer génère le fichier autoload.php, vous pourrez exécuter la commande dump-autoload :

php composer.phar dump-autoload

3.4.4. PSR-4 et la structure du répertoire source du module

Dans Zend Skeleton Application, vous pouvez voir comment la norme PSR-4 est appliquée dans la pratique. Pour le module par défaut de votre site Web, le module Application, les classes PHP déclarées avec l'autoloader standard sont stockées dans le répertoire APP_DIR/module/Application/src ("src" abréviation de "source").

Nous ferons référence au répertoire src en tant que répertoire source du module.

Par exemple, regardons le fichier IndexController.php du module Application (figure 3.2).

Figure 3.2. La structure du répertoire de l'application squelette est conforme à la norme PSR-4 Figure 3.2. La structure du répertoire de l'application squelette est conforme à la norme PSR-4

Comme vous pouvez le voir, il contient la classe IndexController 1 appartenant à l'espace de noms Application\Controller. Pour pouvoir suivre la norme PSR-4 et utiliser l'autoloader standard avec cette classe PHP, nous devons le placer dans le dossier Controller du dossier source du module.

1) La classe IndexController est le contrôleur par défaut de l'application squelette. Nous parlerons des contrôleurs plus loin dans le chapitre Model-View-Controller.


Top