Question

Comme la plupart des développeurs web ces jours-ci, je profite à fond les avantages de l'architecture MVC solide pour les applications Web et des sites. Quand vous faites MVC avec PHP, autoloading est évidemment très pratique.

Je suis devenu fan de spl_autoload_register sur la simple définition d'une seule fonction __autoload(), car cela est évidemment plus souple si vous constituez différents modules de base qui utilisent chacun leur propre autoloading. Cependant, je ne l'ai jamais ressenti une grande sur les fonctions de chargement que je vous écris. Ils impliquent beaucoup de vérification de la chaîne et la numérisation du répertoire afin de rechercher des classes possibles à charger.

Par exemple, disons que j'ai une application qui a un chemin de base défini comme PATH_APP, et une structure simple avec des répertoires nommés models, views et controllers. J'emploie souvent une structure de nommage dans lequel les fichiers sont nommés IndexView.php et IndexController.php dans le répertoire approprié, et les modèles ont généralement pas de régime particulier par défaut. Je pourrais avoir une fonction de chargeur pour cette structure comme celle qui obtient inscrit spl_autoload_register:

public function MVCLoader($class)
{
    if (file_exists(PATH_APP.'/models/'.$class.'.php')) {
        require_once(PATH_APP.'/models/'.$class.'.php');
        return true;
    }
    else if (strpos($class,'View') !== false) {
        if (file_exists(PATH_APP.'/views/'.$class.'.php')) {
            require_once(PATH_APP.'/views/'.$class.'.php');
            return true;
        }
    }
    else if (strpos($class,'Controller') !== false) {
        if (file_exists(PATH_APP.'/controllers/'.$class.'.php')) {
            require_once(PATH_APP.'/controllers/'.$class.'.php');
            return true;
        }
    }
    return false;
}

S'il ne le trouve pas après cela, je pourrais avoir une autre fonction pour scanner les sous-répertoires dans le répertoire des modèles. Cependant, tous les if / else-ing, chaîne de vérification et l'analyse du répertoire me semble inefficace, et je voudrais l'améliorer.

Je suis très curieux de savoir ce nommage des fichiers et des stratégies de autoloading autres développeurs pourraient utiliser. Je suis à la recherche spécifiquement pour les bonnes techniques à employer pour autoloading efficace, et non des alternatives à l'auto-chargement.

Était-ce utile?

La solution

est ce que je l'ai utilisé dans tous mes projets (obtenus directement depuis la source du dernier):

public static function loadClass($class)
{
    $files = array(
        $class . '.php',
        str_replace('_', '/', $class) . '.php',
    );
    foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $base_path)
    {
        foreach ($files as $file)
        {
            $path = "$base_path/$file";
            if (file_exists($path) && is_readable($path))
            {
                include_once $path;
                return;
            }
        }
    }
}

Si je cherche SomeClass_SeperatedWith_Underscores il va rechercher SomeClass_SeperatedWith_Underscores.php suivie SomeClass / SeperatedWith / Underscores.php enraciné dans chaque répertoire dans le courant include_path.

EDIT: Je voulais juste mettre là-bas que j'utilise cette efficacité dans le développement et le traitement pas nécessairement le temps. Si vous avez PEAR sur votre chemin puis avec cela, vous pouvez simplement utiliser les classes et ne pas les inclure lorsque vous en avez besoin.

J'ai tendance à garder mes classes dans une hiérarchie de répertoires, avec des underscores la rupture namespaces ... Ce code me permet de garder la structure de fichiers belle et bien rangé si je veux, ou pour injecter un fichier de classe rapide sans répertoires imbriqués si je veulent (pour l'ajout d'une seule classe ou deux à une bibliothèque qu'il est défendeur, mais ne fait pas partie du projet, je travaille actuellement.)

Autres conseils

je suis tombé sur cette solution:

J'ai créé un script qui parcourt mon dossier bibliothèque de classes (qui contient des sous-dossiers pour les modules / systèmes séparés), et analyse le contenu du fichier à la recherche de définitions de classe. Si elle trouve une définition de classe dans un fichier php (modèle regex assez simple), il crée un lien symbolique:

class_name.php -> actual/source/file.php

Cela me permet d'utiliser une seule, la fonction de chargement automatique simple qui n'a besoin que le nom de classe et le chemin vers le dossier principal de symlink, et ne pas faire toute manipulation chemin / string.

La meilleure partie est que je peux réorganiser mon code source complètement ou ajouter un nouveau sous-système et il suffit d'exécuter le script de génération de lien pour avoir tout automatiquement chargé.

Si vous voulez l'efficacité alors vous ne devriez pas utiliser la fonction de chargement automatique du tout. La fonction de chargement automatique est d'être paresseux. Vous devez fournir un chemin explicite à vos fichiers d'lorsque vous les inclure. Si votre fonction autoload peut trouver ces fichiers, vous pouvez coder les trouver explicitement. Lorsque vous travaillez sur la partie de vue du code et sur le point de charger une nouvelle classe de vue, en laissant la fonction de chargement automatique poignée, il suppose d'abord votre classe est une classe de modèle? C'est inefficace. Au lieu de cela votre code doit être juste:

include_once $this->views_path . $class . '.php';

Si vous avez besoin de plusieurs chemins « vue », une fonction qui charge des vues:

public function load_view($class) {
    // perhaps there's a mapping here instead....
    foreach ($this->views_paths as $path) {
        $filename = $path . $class . '.php';
        if (file_exists($filename)) {
            include_once $filename;
        }
    }
    throw ....
}

Dans tous les cas, au moment où l'inclusion apparaît, vous avez le plus grand / informations les plus précises sur la classe que vous voulez charger. En utilisant cette information pour charger la classe est entièrement la seule stratégie de chargement de classe efficace. Oui, vous pouvez vous retrouver avec plusieurs variables de classe ou (Dieu nous en préserve) quelques variables globales. Mais c'est un meilleur compromis entre les parties que d'être paresseux et balayage du système de fichiers pour votre classe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top