Nette RobotLoader
RobotLoader is a tool that gives you comfort of automated class loading for your entire application including third-party libraries.
- get rid of all
require - only necessary scripts are loaded
- does not require strict directory or file naming conventions
So we can forget about those famous code blocks:
require_once 'Utils/Page.php';
require_once 'Utils/Style.php';
require_once 'Utils/Paginator.php';
// ...
Installation
Download and install the package using Composer:
composer require nette/robot-loader
Usage
Like the Google robot crawls and indexes websites, RobotLoader crawls all PHP scripts and records what classes and interfaces were found in them. These records are then saved in cache and used during all subsequent requests. You just need to specify what directories to index and where to save the cache:
$loader = new Nette\Loaders\RobotLoader;
// Directories for RobotLoader to index (including subdirectories)
$loader->addDirectory(__DIR__ . '/app');
$loader->addDirectory(__DIR__ . '/libs');
// Set caching to the 'temp' directory
$loader->setTempDirectory(__DIR__ . '/temp');
$loader->register(); // Activate RobotLoader
And that's all. From now on, you don't need to use require. Great, isn't it?
When RobotLoader encounters duplicate class name during indexing, it throws an exception and informs you about it. RobotLoader also automatically updates the cache when it has to load a class it doesn't know. We recommend disabling this on production servers, see Caching.
If you want RobotLoader to skip some directories, use $loader->excludeDirectory('temp') (it can be called
multiple times or you can pass multiple directories).
By default, RobotLoader only scans files with the .php extension. To index other file types as well, adjust the
$acceptFiles property, which holds an array of masks:
$loader->acceptFiles = ['*.php', '*.inc'];
The $ignoreDirs property similarly holds masks of directories that are always skipped during scanning (default
.*, *.old, *.bak, *.tmp, temp).
By default, RobotLoader reports errors in PHP files by throwing a ParseError exception. This can be suppressed
using $loader->reportParseErrors(false).
Under the hood, register() hooks the tryLoad() method into PHP's autoloading chain. Whenever PHP
needs an unknown class, interface, trait, or enum, it passes the name to $loader->tryLoad($type), which finds the
matching file and includes it.
Nette Application
Inside a Nette Application, where the $configurator object is used in the Bootstrap.php boot file,
the setup can be simplified:
$configurator = new Nette\Bootstrap\Configurator;
// ...
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->addDirectory(__DIR__ . '/../libs')
->register();
PHP Files Analyzer
RobotLoader can also be used purely for finding classes, interfaces, traits, and enums in PHP files without using the autoloading function:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// Scans directories for classes/interfaces/traits/enums
$loader->rebuild();
// Returns an array of class => filename pairs
$res = $loader->getIndexedClasses();
Even with such usage, you can utilize caching. This ensures that unchanged files won't be rescanned:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
$loader->setTempDirectory(__DIR__ . '/temp');
// Scans directories using cache
$loader->refresh();
// Returns an array of class => filename pairs
$res = $loader->getIndexedClasses();
Caching
RobotLoader is very fast because it cleverly uses caching.
During development, you hardly notice it running in the background. It continuously updates its cache, anticipating that classes and files might be created, deleted, renamed, etc. And it doesn't rescan files that haven't changed.
On a production server, conversely, we recommend disabling cache updates using $loader->setAutoRefresh(false)
(this happens automatically in a Nette Application), because files don't change. At the same time, it's necessary to clear the
cache when uploading a new version to the hosting environment.
The initial scanning of files, when the cache doesn't exist yet, can naturally take a moment for larger applications. RobotLoader has built-in prevention against cache stampede. This is a situation where a large number of concurrent requests on a production server trigger RobotLoader, and since the cache doesn't exist yet, they would all start scanning files, potentially overloading the server. Fortunately, RobotLoader works such that with multiple concurrent requests, only the first thread indexes the files and creates the cache, while the others wait and then use the generated cache.
PSR-4
Nowadays, you can use Composer for autoloading while adhering to
PSR-4. Simply put, it's a system where namespaces and class names correspond to the directory structure and file names, e.g.,
App\Core\RouterFactory will be in the file /path/to/App/Core/RouterFactory.php.
RobotLoader isn't tied to any fixed structure, so it's useful in situations where you don't want the directory structure to exactly match the PHP namespaces, or when developing an application that historically doesn't use such conventions. It's also possible to use both loaders together.