Эффективные стратегии автоматической загрузки и именования PHP - PullRequest
38 голосов
/ 27 апреля 2009

Как и большинство веб-разработчиков в наши дни, я полностью наслаждаюсь преимуществами надежной архитектуры MVC для веб-приложений и сайтов. При выполнении MVC с PHP автозагрузка, очевидно, очень удобна.

Я стал поклонником spl_autoload_register по сравнению с простым определением одной функции __autoload(), поскольку это, очевидно, более гибко, если вы используете разные базовые модули, каждый из которых использует свою собственную автозагрузку. Тем не менее, я никогда не чувствовал себя прекрасно в отношении функций загрузки, которые я пишу. Они включают много проверок строк и сканирование каталогов для поиска возможных классов для загрузки.

Например, допустим, у меня есть приложение, базовый путь которого определен как PATH_APP, и простая структура с каталогами с именами models, views и controllers. Я часто использую структуру именования, в которой файлы с именами IndexView.php и IndexController.php находятся внутри соответствующего каталога, и модели обычно не имеют конкретной схемы по умолчанию. Я мог бы иметь функцию загрузчика для этой структуры, как эта, которая регистрируется с 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;
}

Если после этого он не найден, возможно, у меня есть другая функция для сканирования подкаталогов в каталоге моделей. Однако все операции if / else-проверки, проверки строк и сканирования каталогов кажутся мне неэффективными, и я хотел бы улучшить их.

Мне очень любопытно, какие стратегии именования файлов и автозагрузки могут использовать другие разработчики. Я специально ищу хорошие методы для эффективной автозагрузки, а не альтернативы автозагрузке.

Ответы [ 3 ]

28 голосов
/ 27 апреля 2009

Это то, что я использовал во всех моих проектах (взятых прямо из источника последнего):

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;
            }
        }
    }
}

Если я ищу SomeClass_SeperatedWith_Underscores, он будет искать SomeClass_SeperatedWith_Underscores.php, за которым следует SomeClass / SeperatedWith / Underscores.php с корнем в каждом каталоге в текущем пути включения.

РЕДАКТИРОВАТЬ: Я просто хотел сказать, что я использую это для эффективности в разработке, а не обязательно время обработки. Если у вас есть PEAR на вашем пути, тогда вы можете просто использовать классы и не включать их, когда они вам нужны.

Я стараюсь держать свои классы в иерархии каталогов, с подчеркиванием, разделяющим пространства имен ... Этот код позволяет мне сохранять структуру файла аккуратной и аккуратной, если я хочу, или вводить файл быстрого класса без вложенных каталогов, если я хочу (для добавления одного или двух классов в библиотеку, в которой она является ответчиком, но не является частью проекта, над которым я сейчас работаю.)

13 голосов
/ 27 апреля 2009

Я приземлился на этом решении:

Я создал один скрипт, который пересекает папку моей библиотеки классов (которая содержит подпапки для отдельных модулей / систем) и анализирует содержимое файла в поисках определений классов. Если он находит определение класса в php-файле (довольно простой шаблон регулярных выражений), он создает символическую ссылку:

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

Это позволяет мне использовать одну простую функцию автозагрузки, которая требует только имя класса и путь к главной папке символической ссылки, и не требует каких-либо манипуляций с путем / строкой.

Самое приятное, что я могу полностью изменить свой исходный код или добавить новую подсистему и просто запустить скрипт генерации ссылок, чтобы все автоматически загружалось.

8 голосов
/ 27 апреля 2009

Если вы хотите повысить эффективность, вам вообще не следует использовать функцию автозагрузки. Функция автозагрузки для ленивости. При включении вы должны указать явный путь к вашим файлам включения. Если ваша функция автозагрузки может найти эти файлы, вы можете написать код, чтобы найти их явно. Когда вы работаете над частью представления и собираетесь загрузить новый класс представления, позволяя функции автозагрузки обрабатывать его, сначала предполагается, что ваш класс является классом модели? Это неэффективно. Вместо этого ваш код должен быть просто:

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

Если вам нужно несколько путей «просмотра», создайте функцию, которая загружает представления:

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 ....
}

В любом случае, в момент, когда происходит включение, у вас есть наибольшая / самая точная информация о классе, который вы хотите загрузить. Использование этой информации для полной загрузки класса является единственной эффективной стратегией загрузки классов. Да, вы можете получить больше переменных класса или (боже упаси) некоторые глобальные переменные. Но это лучше, чем просто лениться и сканировать части файловой системы для вашего класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...