Добавлено: Вс Июн 01, 2008 4:38 am (написано за 1 минуту 43 секунды)
Заголовок сообщения: __autoload() с кешированием
Функция автоматически инклудит файлы с классами, см. официальное руководство. Кроме этого, умеет склеивать загруженные автоматически файлы и записывать их в один, а при последующих запусках скрипта — инклудить этот файл, чтобы не дергать лишний раз каждый файл с классом.
Пример кода, который следует разместить где-нибудь вначале скрипта — простой вариант:
Именование и пути Именование классов и структура их папок/файлов должна соответствовать соглашениям по именованию, применяемых в Zend Framework:
Цитата:
Имена классов могут содержать только буквенно-числовые символы. ... Символы нижнего подчеркивания допустимы в местах разделителей пути - имя файла "Zend/Db/Table.php" должно указывать на класс с именем "Zend_Db_Table". ...
Т.е., имя класса разрезается по подчеркиванию "_", все составные части, кроме последней, будут считаться именами папок, а последняя — именем файла.
Подразумевается, что относительные пути и их приоритетность правильным образом заданы разработчиком в include path самостоятельно. Так, если в корне вашего проекта лежит файл lib/DbSimple/Generic.php, то путь к папке <корень проекта>/lib к моменту запуска функции уже должен быть зашит в include path. Поскольку в вышеуказанном файле лежит класс с именем DbSimple_Generic, то функция запросит файл DbSimple/Generic.php с помощью require.
Это основная область применения функции. К стандарту Zend лучше привыкнуть и начать использовать, не зря его написали. Насколько я знаю, стандарт PEAR именует размещает классы по аналогичной схеме.
Можно объявить константу __AUTOLOAD_INCLUDE, которая заставит функцию использовать include вместо require.
Кеширование Если кеширование включено, функция будет склеивать содержимое найденных файлов в один, и при последующих запусках скрипта сначала включать этот файл, а затем пытаться включить прочие файлы, если они еще нужны. И так до тех пор, пока в кеш не будут занесены все-все требуемые когда-либо файлы.
Говорят, при определенных условиях такое склеивание может ускорить работу скриптов.
Чтобы кеширование заработало, нужно сперва определить папку, куда записывать кеш, и файл-семафор (может я неправильно назвал, поправьте если что), который будет управлять кешем — это константы __AUTOLOAD_CACHE_DIR и __AUTOLOAD_MUTEX_FILE соответственно. Причем, чтобы отключить кеширование или перезагрузить кеш заново, нужно либо удалить файл, либо поменять его время модификации соответственно. Т.е., чтобы перегрузить кеш по команде из какой-то программы, достаточно вызвать touch() этого файла.
Запись в файл кеша происходит при завершении работы скрипта. Можно, конечно, вызвать __autoload() напрямую где-нибудь в конце скрипта, но лучше сделать это автоматически, с помощью register_shutdown_function(). Такой способ позволит делать запись кеша в максимально удобный момент.
Имя файла кеша будет содержать метку времени файла-семафора. Если метка времени семафора поменялась, будет просто создан новый файл кеша с новой меткой. С каждым дописыванием, функция вставляет комментарий с меткой времени, когда файл был дописан.
Надежность и эффективность При автозагрузке файла, происходит такой же require, как будто бы вы делали его вручную из скрипта. Любые ошибки здесь неуместны, поэтому при малейшей проблеме будет вылетать Fatal error. На первый взгляд это может показаться неудобным, но на самом деле это отличный повод сделать все ваши классы по единому строгому стандарту. То же касается путей: папка с кешем должна быть доступна для записи, либо чтобы была возможность ее создать (функция об этом позаботится сама, или опять же, бросится ошибкой).
Сам файл кеша не представляет какой-либо секретности, если ваши автоматически загружаемые файлы содержат только объявления классов. Иными словами, разработчик сам отвечает за целостность и адекватность пространства имен классов, вызовы функций, объявления констант и так далее. Желающим настроить доступ к файлам по-своему, предоставляется возможность в виде констант __AUTOLOAD_DIR_MODE и __AUTOLOAD_FILE_MODE, которые можно определить до запуска функции.
Файлы должны начинаться с открывающего тега PHP: '<?php'. Крайне нежелательно, чтобы файлы заканчивались завершающим тегом '?>', но функция умеет отрезать последний закрывающий тег.
Функция еще не тестировалась в "production"-среде. Потенциально, у нее могут быть проблемы с одновременным обращением нескольких процессов к файлу в момент записи. Я решил не добавлять блокировку файла, потому что эффект их действия мне неизвестен. Также, используется clearstatcache() - лично мне неизвестно, наносит ли это удар по производительности.
Буду рад получить отзывы по использованию функции. Всем спасибо заранее.
Добавлено: Вт Июн 03, 2008 3:27 pm (спустя 2 дня 10 часов 49 минут; написано за 8 минут 15 секунд)
Заголовок сообщения: Re: __autoload() с кешированием
Спасибо за труд, работает на ура. Но, есть один минус. По Вашей схеме - в одном файле должен быть один класс. Если же их больше, то появляются баги. Например, библиотека MDB2 ругается так :
Цитата:
Cannot redeclare class MDB2_Error in /usr/share/php/pear/MDB2.php on line 977
Все потому, что в файле MDB2.php находятся описание классов MBD2, MDB2_Error и др.
UPD. Поправлюсь. Ошибка в другом. PEER-овские require_once-ы сводят на нет весь скрипт :( Так как глупо лезть в PEER библиотеки и убирать все вызовы require_once, было принято решение не кешировать эти библиотеки. Есть-ли другие варианты?
Добавлено: Ср Июн 18, 2008 4:32 pm (спустя 10 дней 17 часов 58 минут; написано за 2 минуты 26 секунд)
Заголовок сообщения:
Как-нибудь на досуге попробую модифицировать скрипт так, чтобы при кешировании сам убирал все вызовы require_once. Тогда и вырезать ничего не надо будет :)
Добавлено: Чт Июн 19, 2008 3:47 pm (спустя 14 часов 26 минут; написано за 4 минуты 32 секунды)
Заголовок сообщения:
Да, боюсь что так. Помимо банальных конструкций require/include_once('filename'), которые вырезать несложно, нашел в PEER-овских библиотеках несколько встроенных автолоадеров с хитрой логикой. Убирать их скриптом - чистой воды шаманство.
Добавлено: Ср Авг 13, 2008 11:10 am (спустя 1 месяц 23 дня 19 часов 22 минуты; написано за 1 минуту 35 секунд)
Заголовок сообщения:
Можно и не убирать, а где-нибудь просто создать пустые (или почти пустые) файлы и подменить include_path так, чтобы require_once включал именно эти пустые файлы. Я это не пробовал, просто идея.
Тогда не надо будет ни PEAR менять, ни Zend Framework.
Вы не можете начинать темы. Вы не можете отвечать на сообщения. Вы не можете редактировать свои сообщения. Вы не можете удалять свои сообщения. Вы не можете голосовать в опросах. Вы не можете прилагать файлы к сообщениям. Вы можете скачивать файлы.