web-dev-qa-db-fra.com

Comment utiliser spl_autoload_register pour plusieurs répertoires en PHP?

J'essaie en fait de créer un cadre MVC pour moi-même, mais j'ai des problèmes avec le chargement automatique. Ce n'est pas un problème en fait, mais je voudrais demander aux gourous, comment utilisent-ils le spl_autoload_register fonctionne lorsqu'il existe différents répertoires.

Disons que nous avons les répertoires suivants:

Controllers
Libs
Models

Chaque dossier contient différentes classes, comme:

Controllers:
   Main.php
   File.php
   About.php
Libs:
   Main.php
   Front_controller.php
Models:
   Index.php
   File.php
   Login.php

Vous pouvez remarquer que certains noms de fichiers peuvent être trouvés avec le même nom dans différents répertoires. D'accord, voici donc ce que j'ai essayé jusqu'à présent:

spl_autoload_register(function ($class) { 

    $pathContorllers = 'Controllers/' . $class . '.php';
    $pathLibs = 'Libs/' . $class . '.php';
    $pathModels = 'Models/' . $class . '.php';

    if (file_exists($pathContorllers)) {
        require_once $pathContorllers;
    } elseif (file_exists($pathLibs)) {
        require_once $pathLibs;
    } elseif (file_exists($pathModels )) {
        require_once $pathModels ;
    }
});

Cela fonctionne bien, mais je suis sûr qu'il existe un autre moyen de simplifier les choses. Quelqu'un peut-il me suggérer comment améliorer ou simplifier ce code/quels gourous utilisent dans cette situation?

18
Radical_Activity

Dans le but d'empêcher les personnes susceptibles de rencontrer cette réponse d'obtenir des informations obsolètes, je les ai mises à jour en ce qui concerne les dernières normes de chargement automatique du PSR. La réponse originale a été conservée à des fins historiques et pour ceux qui ne sont intéressés que par l'autochargeur PSR-0.

Réponse mise à jour

PHP-FIG a officiellement déprécié la norme PSR- en faveur de l'autochargeur alternatif, PSR-4 . Bien que les deux soient similaires à certains égards, ils sont également très différents à d'autres. (Par exemple: la gestion des traits de soulignement dans les noms de classe.)

Vous pensez peut-être à vous-même - "J'utilise PSR-0 maintenant et cela fonctionne très bien." La vérité est que PSR-0 fonctionnera toujours bien pour certains projets. Cela est particulièrement vrai en cas de compatibilité descendante avec un package qui n'utilise pas d'espaces de noms. PSR-0 est toujours un principe de chargement automatique décent, mais il a ses propres défauts .

Bien sûr, s'il y a une chose qui est constante dans la programmation, c'est que le code finit par changer et que les techniques de programmation continuent d'évoluer. Vous pouvez vous faire une faveur aujourd'hui en vous préparant pour demain. Par conséquent, si vous venez de démarrer un projet ou essayez de porter un projet vers une version plus récente de PHP qui peut utiliser des espaces de noms, vous devriez sérieusement envisager d'utiliser l'autochargeur PSR-4.

Il convient également de noter que si vous développez un projet qui n'utilise pas d'espaces de noms, le PSR-4 ne s'applique pas à vous. Dans ce cas, PSR-0 ou votre propre chargeur automatique personnalisé s'applique.


Réponse originale

Si vous souhaitez utiliser des espaces de noms dans vos classes, la route PSR- est un assez bon moyen de charger automatiquement. Fondamentalement, votre espace de noms vous représente la structure de répertoires et les classes peuvent être chargées en fonction d'une convention.

Si la méthode PSR-0 ne répond pas à tous vos besoins (ou ne joue pas Nice avec le code existant), vous pouvez toujours ajouter plus de fonctions avec spl_autoload_register et PHP les parcourra un par un pour tenter de charger les classes.

Exemple d'utilisation:

La première chose est d'abord, si vous n'êtes pas familier avec espaces de noms en PHP alors vous bénéficierez de consulter le manuel PHP sur le sujet. Ils peuvent être un peu déroutant au début, mais leurs avantages valent la confusion initiale.

J'ai donc dit que PSR-0 fonctionne en associant vos espaces de noms à votre structure de répertoires. Utilisons vos répertoires comme exemple. Vous avez dans votre dossier racine (où qu'il se trouve) les éléments suivants:

Project directory:  <- Let's call this directory "MyProject"
    Controllers:
       Main.php
       File.php
       About.php
    Libs:
       Main.php
       Front_controller.php
    Models:
       Index.php
       File.php
       Login.php
index.php <- Let's say this is your entry point file, this is where you will be autoloading stuff from.

Jetons maintenant un œil à votre contrôleur Main.php. Deux choses à garder à l'esprit sont que le nom de la classe doit être le nom du fichier et que l'espace de noms de cette classe est le chemin d'accès au répertoire de ce fichier. Alors Main.php devrait ressembler à ceci:

<?php

namespace MyProject\Controllers;

class Main {

    //Field vars, contructor, methods, etc. all go here.

}

?>

Vous feriez la même chose pour votre modèle Login

<?php

namespace MyProject\Models;

class Login {

    //Field vars, contructor, methods, etc. all go here.

}

?>

Maintenant dans votre index.php fichier (dans le répertoire racine - MyProject) vous feriez votre appel au spl_autoload_register et donnez-lui l'autochargeur PSR-0.

spl_autoload_register( function ($className) {
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    require $fileName;
});

//Now you can make your call to your objects without a bunch of include/require statements

$main = new \MyProject\Controllers\Main();  //Instantiates your 'Main' controller
$login = new \MyProject\Models\Login();   //Instantiates your 'Login' model

Espérons que cela aide à mieux le comprendre, et encore une fois, si vous ne voulez pas utiliser d'espaces de noms, vous pouvez toujours continuer à ajouter des fermetures dans la pile de chargement automatique SPL. Vous pouvez avoir 10 chargeurs automatiques différents si vous le souhaitez et PHP les parcourra un par un (dans l'ordre que vous les avez défini) en utilisant chaque fonction pour essayer de charger une classe. Cependant, un les chargeurs automatiques basés sur des conventions de couple sont un peu plus propres et plus une méthode préférée. N'oubliez pas non plus que le chargeur automatique traduit les deux séparateurs d'espace de noms \ et souligne _ comme séparateur de répertoire. Alors votre Front_controller.php ne se chargerait pas automatiquement comme prévu.

34
Crackertastic

Le code ci-dessous vous aidera. Mais je vous conseille de vérifier les espaces de noms.

spl_autoload_register ( function ($class) {

$sources = array("Controllers/$class.php", "Lib/$class.php ",  "Models/$class.php " );

    foreach ($sources as $source) {
        if (file_exists($source)) {
            require_once $source;
        } 
    } 
});
8
user3563950