Zend Framework

индекс
75,79

Накопительная сборка ZF в один файл

В тему объединения PHP-классов в Zend Framework'е (и других, следующих таким же соглашениям наименования и размещения) публикую свое решение, реализующее __autoload с накопительной сборкой автозагружаемых классов.

В нем учтены две известные проблемы:
  1. В файлах содержащих переменную __FILE__ осуществляется подстановка этой переменной.
  2. Обрабатывается случай параллельного выполнения скриптов.

Решение базируется на примере реализации __autoload из книги Дмитрия Котерова по PHP5 и идее описанной тут.

Применение


Применяется все это таким образом:
1. Где-то в начале работы скрипта, но после инициализации путей к библиотекам (set_include_path(...)) добавляем:
require_once "My/NameScheme/Autoload.php";
if (@fopen('All.php', 'r', true)) {
  include_once('All.php');
}

2. Где-то при завершении работы скрипта (можно и в register_shutdown_function поместить, но я так не пробовал) добавляем:
My_NameScheme_Autoload::compileTo(APP_ROOT . '/includes/All.php'); //где путь к файлу должен быть актуальным для вашего случая


Конечно же, чтобы все это заработало нужно предварительно в Zend Framework'е вырезать все require|include
Я использую для этого такой прием:
$file = preg_replace('/((?:require|include)_once\s*\(?[\'"]Zend\/(.*)[\'"]\)?\s*;)/smiU', '//*** $1', $file);


Для сброса кеша нужно просто удалить All.php, создастся новый и он будет расти пока пользователи не обойдут все «закоулки» сайта. Однако, тут я иногда встречаю одну проблему: из-за частого изменения (в процессе роста) All.php FastCGI-процессы начинают сильно грузить систему, поэтому после удаления иногда приходится перегружать FastCGI-процессы вручную.

Алгоритм


В случае, если были автозагружены какие-либо новые файлы алгоритм работы метода compileTo заключается в следующем:
  1. Блокируем All.php
  2. Проверяем нет ли уже в All.php классов, которые были также и автозагружены (например, пока отрабатывал данный скрипт, в параллели другой скрипт успешно отбработал и что-то дозаписал в All.php). Если такое произошло, то во избежание проблем с зависимостями работа метода будет прервана.
  3. Дописываем в All.php новые классы.
  4. Разблокируем All.php.

Скачать


autoload.zip (6 Кб)
0
7 марта 2010, 01:37
13

комментарии (7)

0
TuiKiken #
Спасибо, на днях попробую.
0
cids #
Класс PHP_Autoload ваш? Лично у меня была проблема (не с вашей библиотекой) с регистрацией автолоадера путем банального объявления функции __autoload(), вместо этого пришлось писать spl_autoload_register(), из чего делаю вывод, что работать будет не всегда. Использование PEAR_NameScheme — сильное замедление — от там тыркается по всем путям из include path с проверкой на наличие файла (сам). Вот, к примеру, стандартный Zend_Loader делает это вызовом include(_once), делегируя проверку существования файла движку, что, думаю, быстрее.
0
macondos #
Не, мое только My_NameScheme_Autoload (собственно он ведь также и решает проблему неоптимального «тыркания» по всем путям)
0
cids #
Решает ли? My_NameScheme_Autoload::classAutoloader() использует PEAR_NameScheme::name2path(), а там перебор по PEAR_NameScheme::getInc(), который в свою очередь возвращает массив путей из include_path + пользуется не оптимальной (по мнению разработчиков Zend_Loader) проверкой file_exists

        foreach (PEAR_NameScheme::getInc($absolutize) as $libDir) {
            $path = $libDir . '/' . $fname;
            if (file_exists($path)) {
                if (!$absolutize) return $fname;
                else return $path;
            }
        }


А вот ту Вы уже полученный финальный путь опять проверяете на существование, но уже «оптимально» =). Кстати, что вернет fopen(false, "r", true)? Ведь такой вариант событий не исключен, судя по коду PEAR_NameScheme::name2path().
0
macondos #
Я о том, что после однократного формирования сборки All.php никакие include уже не используются (для чего все и задумывалось).
0
cids #
А __autoload() после этого вы уже не регистрируете?
0
macondos #
Регистрирую, но он ни разу не срабатывает, т.к. все классы уже загружены сборкой.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.