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, или когда вы разрабатываете приложение, которое исторически таких соглашений не использует. Также возможно использовать оба загрузчика вместе.

версия: 4.0