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-скрипти та записує, які класи, інтерфейси, трейти та enum він у них знайшов. Результати дослідження він потім зберігає в кеші та використовує при наступному запиті. Достатньо лише вказати, які каталоги він має сканувати та куди зберігати кеш:

$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 також автоматично оновлює кеш, коли має завантажити клас, який він не знає. Це рекомендується вимкнути на робочих серверах, див. Кешування.

Якщо ви хочете, щоб 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 можна також використовувати суто для пошуку класів, інтерфейсів, трейтів та enum у файлах PHP без використання функції автозавантаження:

$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');

// просканує каталоги на класи / інтерфейси / трейти / enum
$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 дуже швидкий, оскільки вміло використовує кеш.

Під час розробки ви практично не помічаєте, що він працює у фоновому режимі. Він постійно оновлює свій кеш, оскільки враховує, що класи та файли можуть створюватися, зникати, перейменовуватися тощо. І він не сканує повторно файли, які не змінилися.

При розгортанні на робочому сервері, навпаки, рекомендується вимкнути оновлення кешу за допомогою $loader->setAutoRefresh(false) (у Nette Application це відбувається автоматично), оскільки файли не змінюються. Водночас необхідно при завантаженні нової версії на хостинг видалити кеш.

Початкове сканування файлів, коли кеш ще не існує, може, звісно, зайняти деякий час для великих програм. RobotLoader має вбудований захист від cache stampede. Це ситуація, коли на робочому сервері збирається велика кількість одночасних запитів, які запускають RobotLoader, і оскільки кеш ще не існує, всі вони починають сканувати файли. Що б надмірно навантажило сервер. На щастя, RobotLoader працює так, що при кількох одночасних запитах індексує файли лише перший потік, створює кеш, інші чекають і потім використовують кеш.

PSR-4

Сьогодні для автозавантаження можна використовувати Composer при дотриманні PSR-4. Спрощено кажучи, це система, коли простори імен та назви класів відповідають структурі каталогів та назвам файлів, тобто, наприклад, App\Core\RouterFactory буде у файлі /path/to/App/Core/RouterFactory.php.

RobotLoader не пов'язаний з жодною фіксованою структурою, тому він підходить у ситуаціях, коли вам не зовсім зручно мати однаково спроектовану структуру каталогів, як простори імен у PHP, або коли ви розробляєте програму, яка історично не використовує таких конвенцій. Можливо також використовувати обидва завантажувачі разом.

версія: 4.0