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.

Version: 4.0