RobotLoader: Autoloading von Klassen
RobotLoader ist ein Werkzeug, das Ihnen den Komfort des automatischen Ladens von Klassen für Ihre gesamte Anwendung einschließlich Bibliotheken von Drittanbietern bietet.
- wir werden alle
require
los - es werden nur die benötigten Skripte geladen
- erfordert keine strengen Konventionen zur Benennung von Verzeichnissen oder Dateien
- extrem schnell
- keine manuellen Cache-Updates, alles geschieht automatisch
- eine ausgereifte, stabile und weit verbreitete Bibliothek
Wir können also diese bekannten Codeblöcke vergessen:
require_once 'Utils/Page.php';
require_once 'Utils/Style.php';
require_once 'Utils/Paginator.php';
// ...
Installation
Sie können RobotLoader als eine
einzelne separate Datei RobotLoader.php
herunterladen, die Sie mit require
in Ihr Skript einbinden
und sofort komfortables Autoloading für die gesamte Anwendung zur Verfügung haben.
require '/path/to/RobotLoader.php';
$loader = new Nette\Loaders\RobotLoader;
// ...
Wenn Sie eine Anwendung mit Composer erstellen, können Sie ihn damit installieren:
composer require nette/robot-loader
Verwendung
Ähnlich wie der Google-Roboter Webseiten durchsucht und indiziert, durchsucht auch RobotLoader alle PHP-Skripte und merkt sich, welche Klassen, Schnittstellen, Traits und Enums er darin gefunden hat. Die Ergebnisse der Suche speichert er dann im Cache und verwendet sie bei der nächsten Anfrage. Es genügt also, anzugeben, welche Verzeichnisse er durchsuchen und wo er den Cache speichern soll:
$loader = new Nette\Loaders\RobotLoader;
// Verzeichnisse, die RobotLoader indizieren soll (einschließlich Unterverzeichnissen)
$loader->addDirectory(__DIR__ . '/app');
$loader->addDirectory(__DIR__ . '/libs');
// wir stellen das Caching auf das Verzeichnis 'temp' ein
$loader->setTempDirectory(__DIR__ . '/temp');
$loader->register(); // wir starten RobotLoader
Und das ist alles, von diesem Moment an müssen wir require
nicht mehr verwenden. Großartig!
Wenn RobotLoader bei der Indexierung auf einen doppelten Klassennamen stößt, löst er eine Ausnahme aus und informiert Sie darüber. RobotLoader aktualisiert den Cache auch automatisch, wenn er eine Klasse laden soll, die er nicht kennt. Wir empfehlen, dies auf Produktionsservern zu deaktivieren, siehe Caching.
Wenn Sie möchten, dass RobotLoader einige Verzeichnisse überspringt, verwenden Sie
$loader->excludeDirectory('temp')
(kann mehrmals aufgerufen oder mehrere Verzeichnisse übergeben werden).
Standardmäßig meldet RobotLoader Fehler in PHP-Dateien durch Auslösen einer ParseError
-Ausnahme. Dies kann mit
$loader->reportParseErrors(false)
unterdrückt werden.
Nette-Anwendung
Innerhalb einer Nette-Anwendung, wo in der Startdatei Bootstrap.php
das Objekt $configurator
verwendet wird, kann die Notation vereinfacht werden:
$configurator = new Nette\Bootstrap\Configurator;
// ...
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->addDirectory(__DIR__ . '/../libs')
->register();
Analysator für PHP-Dateien
RobotLoader kann auch ausschließlich zum Suchen von Klassen, Schnittstellen, Traits und Enums in PHP-Dateien verwendet werden, ohne die Autoloading-Funktion zu nutzen:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// durchsucht Verzeichnisse nach Klassen / Schnittstellen / Traits / Enums
$loader->rebuild();
// gibt ein Array von Paaren Klasse => Dateiname zurück
$res = $loader->getIndexedClasses();
Auch bei einer solchen Verwendung können Sie den Cache nutzen. Dadurch werden unveränderte Dateien bei einem erneuten Scan nicht erneut analysiert:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// wir stellen das Caching auf das Verzeichnis 'temp' ein
$loader->setTempDirectory(__DIR__ . '/temp');
// durchsucht Verzeichnisse unter Verwendung des Caches
$loader->refresh();
// gibt ein Array von Paaren Klasse => Dateiname zurück
$res = $loader->getIndexedClasses();
Caching
RobotLoader ist sehr schnell, da er den Cache geschickt nutzt.
Während der Entwicklung merkt man praktisch nicht, dass er im Hintergrund läuft. Er aktualisiert den Cache kontinuierlich, da er davon ausgeht, dass Klassen und Dateien entstehen, verschwinden, umbenannt werden usw. Und er scannt Dateien, die sich nicht geändert haben, nicht erneut.
Beim Einsatz auf einem Produktionsserver empfehlen wir jedoch, die Cache-Aktualisierung mit
$loader->setAutoRefresh(false)
zu deaktivieren (in einer Nette-Anwendung geschieht dies automatisch), da sich die
Dateien nicht ändern. Gleichzeitig ist es dann notwendig, beim Hochladen einer neuen Version auf den Hosting-Server den Cache
zu löschen.
Das anfängliche Scannen von Dateien, wenn der Cache noch nicht existiert, kann bei umfangreicheren Anwendungen natürlich einen Moment dauern. RobotLoader verfügt über eine integrierte Prävention gegen Cache Stampede. Dies ist eine Situation, in der auf einem Produktionsserver eine größere Anzahl gleichzeitiger Anfragen eingeht, die RobotLoader starten, und da der Cache noch nicht existiert, würden alle beginnen, die Dateien zu scannen. Dies würde den Server unverhältnismäßig belasten. Glücklicherweise funktioniert RobotLoader so, dass bei mehreren gleichzeitigen Anfragen nur der erste Thread die Dateien indiziert, den Cache erstellt, die anderen warten und anschließend den Cache nutzen.
PSR-4
Heute kann für das Autoloading Composer verwendet
werden, wenn PSR-4 eingehalten wird. Vereinfacht gesagt handelt es sich um ein System, bei dem Namensräume und Klassennamen
der Verzeichnisstruktur und den Dateinamen entsprechen, d. h. z. B. App\Core\RouterFactory
befindet sich in der Datei
/path/to/App/Core/RouterFactory.php
.
RobotLoader ist nicht an eine feste Struktur gebunden und eignet sich daher für Situationen, in denen es Ihnen nicht ganz passt, eine Verzeichnisstruktur zu haben, die wie die Namensräume in PHP aufgebaut ist, oder wenn Sie eine Anwendung entwickeln, die historisch solche Konventionen nicht verwendet. Es ist auch möglich, beide Loader zusammen zu verwenden.