RobotLoader: autoloading на класове

RobotLoader е инструмент, който ще ви осигури комфорта на автоматичното зареждане на класове за цялото ви приложение, включително библиотеки на трети страни.

  • ще се отървем от всички require
  • ще се зареждат само необходимите скриптове
  • не изисква строги конвенции за именуване на директории или файлове
  • изключително бърз
  • никакви ръчни актуализации на кеша, всичко протича автоматично
  • зряла, стабилна и широко използвана библиотека

Следователно можем да забравим за тези познати блокове код:

require_once 'Utils/Page.php';
require_once 'Utils/Style.php';
require_once 'Utils/Paginator.php';
// ...

Инсталация

Можете да изтеглите RobotLoader като един отделен файл RobotLoader.php, който да вмъкнете с require във вашия скрипт и веднага имате на разположение комфортен autoloading за цялото приложение.

require '/path/to/RobotLoader.php';

$loader = new Nette\Loaders\RobotLoader;
// ...

Ако изграждате приложение, използващо Composer, можете да го инсталирате с негова помощ:

composer require nette/robot-loader

Използване

Подобно на това как Google robot обхожда и индексира уеб страници, така и 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 също така автоматично актуализира кеша, когато трябва да зареди клас, който не познава. Препоръчваме да изключите това на продукционни сървъри, вижте Кеширане.

Ако искате RobotLoader да пропусне някои директории, използвайте $loader->excludeDirectory('temp') (може да се извиква многократно или да се предадат повече директории).

По подразбиране RobotLoader съобщава за грешки в PHP файловете чрез хвърляне на изключение ParseError. Това може да бъде потиснато с помощта на $loader->reportParseErrors(false).

Nette приложение

Вътре в Nette приложение, където се използва обектът $configurator в зареждащия файл Bootstrap.php, записът може да бъде опростен:

$configurator = new Nette\Bootstrap\Configurator;
// ...
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
	->addDirectory(__DIR__)
	->addDirectory(__DIR__ . '/../libs')
	->register();

Анализатор на PHP файлове

RobotLoader може да се използва и чисто за търсене на класове, интерфейси, трейтове и енуми в PHP файлове без използване на функцията за autoloading:

$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 е много бърз, защото умело използва кеша.

При разработка практически не усещате, че работи на заден план. Непрекъснато актуализира кеша си, защото разчита на това, че класове и файлове могат да възникват, изчезват, да се преименуват и т.н. И не сканира повторно файлове, които не са се променили.

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

Първоначалното сканиране на файлове, когато кешът още не съществува, може при по-обширни приложения разбираемо да отнеме малко време. RobotLoader има вградена превенция срещу cache stampede. Става въпрос за ситуация, когато на продукционен сървър се съберат по-голям брой едновременни заявки, които стартират RobotLoader, и тъй като кешът още не съществува, всички биха започнали да сканират файлове. Което би натоварило непропорционално сървъра. За щастие RobotLoader работи така, че при повече едновременни заявки файловете се индексират само от първата нишка, създава се кеш, останалите чакат и впоследствие използват кеша.

PSR-4

Днес може да използвате Composer за autoloading при спазване на PSR-4. Просто казано, става въпрос за система, при която пространствата от имена и имената на класовете съответстват на директорийната структура и имената на файловете, т.е. напр. App\Core\RouterFactory ще бъде във файла /path/to/App/Core/RouterFactory.php.

RobotLoader не е свързан с никаква фиксирана структура, затова е подходящ в ситуации, когато не ви е напълно удобно да имате еднакво проектирана директорийна структура като пространствата от имена в PHP, или когато разработвате приложение, което исторически не използва такива конвенции. Възможно е също така да се използват и двата loader-а заедно.

версия: 4.0