RobotLoader: автозагрузка классов
RobotLoader — это инструмент, который обеспечит вам комфорт автоматической загрузки классов для всего вашего приложения, включая сторонние библиотеки.
- избавимся от всех
require
- будут загружаться только необходимые скрипты
- не требует строгих соглашений по именованию каталогов или файлов
- чрезвычайно быстрый
- никакой ручной актуализации кеша, все происходит автоматически
- зрелая, стабильная и широко используемая библиотека
Таким образом, мы можем забыть об этих известных блоках кода:
require_once 'Utils/Page.php';
require_once 'Utils/Style.php';
require_once 'Utils/Paginator.php';
// ...
Установка
RobotLoader можно скачать как один отдельный файл
RobotLoader.php
, который вы включите с помощью require
в свой
скрипт, и сразу же получите удобную автозагрузку для всего
приложения.
require '/path/to/RobotLoader.php';
$loader = new Nette\Loaders\RobotLoader;
// ...
Если вы создаете приложение, использующее Composer, вы можете установить его с помощью него:
composer require nette/robot-loader
Использование
Подобно тому, как робот Google обходит и индексирует веб-страницы, так и RobotLoader обходит все PHP-скрипты и записывает, какие классы, интерфейсы, трейты и перечисления он в них нашел. Результаты сканирования он затем сохраняет в кеш и использует при следующем запросе. Достаточно лишь указать, какие каталоги он должен обходить и куда сохранять кеш:
$loader = new Nette\Loaders\RobotLoader;
// каталоги, которые RobotLoader должен индексировать (включая подкаталоги)
$loader->addDirectory(__DIR__ . '/app');
$loader->addDirectory(__DIR__ . '/libs');
// установим кеширование в каталог 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
$loader->register(); // запустим RobotLoader
И это все, с этого момента нам не нужно использовать require
.
Отлично!
Если RobotLoader при индексации столкнется с дублирующимся именем класса, он выбросит исключение и сообщит вам об этом. RobotLoader также автоматически обновляет кеш, когда ему нужно загрузить класс, который он не знает. Это рекомендуется отключать на production-серверах, см. #Кеширование.
Если вы хотите, чтобы RobotLoader пропустил какие-то каталоги, используйте
$loader->excludeDirectory('temp')
(можно вызывать многократно или передать
несколько каталогов).
По умолчанию RobotLoader сообщает об ошибках в PHP-файлах, выбрасывая
исключение ParseError
. Это можно подавить с помощью
$loader->reportParseErrors(false)
.
Приложение Nette
Внутри приложения Nette, где в загрузочном файле Bootstrap.php
используется объект $configurator
, запись можно упростить:
$configurator = new Nette\Bootstrap\Configurator;
// ...
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->addDirectory(__DIR__ . '/../libs')
->register();
Анализатор PHP-файлов
RobotLoader можно также использовать исключительно для поиска классов, интерфейсов, трейтов и перечислений в PHP-файлах без использования функции автозагрузки:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// просканирует каталоги на наличие классов / интерфейсов / трейтов / перечислений
$loader->rebuild();
// возвращает массив пар класс => имя файла
$res = $loader->getIndexedClasses();
Даже при таком использовании вы можете использовать кеш. Благодаря этому при повторном сканировании не будут повторно анализироваться неизмененные файлы:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// установим кеширование в каталог 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
// просканирует каталоги с использованием кеша
$loader->refresh();
// возвращает массив пар класс => имя файла
$res = $loader->getIndexedClasses();
Кеширование
RobotLoader очень быстр, потому что он умно использует кеш.
При разработке вы практически не замечаете, что он работает в фоновом режиме. Он постоянно обновляет кеш, так как учитывает, что классы и файлы могут создаваться, удаляться, переименовываться и т.д. И он повторно не сканирует файлы, которые не изменились.
При развертывании на production-сервере, наоборот, рекомендуется
отключить обновление кеша с помощью $loader->setAutoRefresh(false)
(в
приложении Nette это происходит автоматически), так как файлы не
меняются. При этом необходимо при загрузке новой версии на хостинг
очистить кеш.
Первоначальное сканирование файлов, когда кеш еще не существует, может у более крупных приложений, естественно, занять некоторое время. RobotLoader имеет встроенную защиту от cache stampede. Это ситуация, когда на production-сервере собирается большое количество одновременных запросов, которые запускают RobotLoader, и поскольку кеш еще не существует, все они начали бы сканировать файлы. Что непропорционально нагрузило бы сервер. К счастью, RobotLoader работает так, что при нескольких одновременных запросах файлы индексирует только первый поток, создает кеш, остальные ждут и впоследствии используют кеш.
PSR-4
Сегодня для автозагрузки
можно использовать Composer при соблюдении PSR-4. Проще говоря, это
система, когда пространства имен и имена классов соответствуют
структуре каталогов и именам файлов, то есть, например,
App\Core\RouterFactory
будет в файле /path/to/App/Core/RouterFactory.php
.
RobotLoader не связан ни с какой фиксированной структурой, поэтому он подходит в ситуациях, когда вам не совсем удобно иметь одинаково спроектированную структуру каталогов, как пространства имен в PHP, или когда вы разрабатываете приложение, которое исторически таких соглашений не использует. Также возможно использовать оба загрузчика вместе.