onPHP/onphp-framework — pull request #124 by AlexeyDsov (2012-08-07 14:38:41+00:00)
Title: Autoloader exp (Заготовка реквеста)

Взялся немножко исправить автолоадер и в итоге захотел переписать больше чем изначально планировал.

Список изменений примерно таков:

1. Автолоадеры разделены на отдельные классы. Теперь они не статические и создаются через new или статический вызов create. Не кеширующий автолоадер называется AutoloaderNoCache, кэширующий пути к классам AutoloaderClassPathCache, полностью кэширующий все классы в один файл был удален, т.к. в случае неймспейсов в таком виде его использовать нельзя + подозреваю что его никто действительно не использовал.
1. Автолоадеры теперь не используют ```(get|set)_include_path```. Взамен этому каждому автолоадеру можно засетить набор директорий в которых нужно искать классы.
1. В случае вызова методов class_exists, interface_exists, trait_exists теперь не выкидывается ошибка ClassNotFoundException. Взамен этого они корректно возвращают true/false. Реализовано эта фича за счет специально AutoloaderClassNotFound оказывающегося в конец стэка spl_autoloader'ов и бросающим/небросающим ошибку в зависимости а trace'а.
1. Что бы корректно включить какой-либо автолоадер в стэк spl_autoloader'ов необходимо вызвать у него метод register.
1. В случае подключения внешних автолоадеров желательно затем ```AutoloaderClassNotFound::me()->register();``` Это перенесет его вызов AutoloaderClassNotFound в самый конец стэка spl_autoloader'ов.
1. AutoloaderNoCache и AutoloaderClassPathCache используют (необходимо им засетить) классы NamespaceResolver(OnPHP|PSR0). Это что-то вроде задела на будуйщее и для тех кто вдруг уже захотел использовать неймспейсы в каком-то виде в своем проекте.
* NamespaceResolverOnPHP не используют никак иерархию папок, каждый директория задается ему отдельно вместе с неймспейсом для нее
* NamespaceResolverPSR0 ведет похоже на [PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) за двумя исключениями:
* 1. конвертирования символа '_' в DIRECTORY_SEPARATOR, т.к. иначе в таком случае невозможно однозначно выполнить обратную операцию - по пути файла определить имя класса, а это необходимо в случае использования AutoloaderClassPathCache.
* 2. По умолчанию постфиксом файла класса считается ```.class.php``` вместо ```.php```, но его можно переназначать на любой желаемый.
* В случае использования AutoloaderClassPathCache и кэширования путей до классов разницы в производительности между двумя NamespaceResolver'ами впринципе нету. В обоих случаях они один раз возвращают путь, он кэшируется и больше их не спрашивают о пути, пока не натыкаются не класс, которого нету.
1. В ходе экспериментов было удобно сделать статический класс для хранения onPHP автолоадеров - AutoloaderPool с методами set, get, drop. Дефолтный автолоадер используемый в onPHP достается через него так: ```AutoloaderPool::get('onPHP')```
1. Так же в AutoloaderPool был добавлен дополнительный функционал, для регистрации автолоадеров со способностью кэширования для вызова их со сбрасыванием кэша.

Что ломается/нужно переделывать:

1. Если кто-то оборачивал class_exists, inteface_exists, trait_exists try/catch/ClassNotFoundException - теперь такой ошибки бросаться не будет.
1. Если кто-то использовать Assert::classExists, то сейчас он бросает WrongArgumentException вместо ClassNotFoundException. Тут можно оставить что б бросался ClassNotFoundException. Не могу сказать как оно должно быть правильней.
1. Заменить ```set_include_path``` конструкцию на ```AutoloaderPool::get('onPHP')->addPaths(array(..., ...));``` либо на использование своего автолоадера.