Nette RobotLoader

RobotLoader ist ein Werkzeug, das Ihnen den Komfort des automatischen Ladens von Klassen für Ihre gesamte Anwendung einschließlich Bibliotheken Dritter verschafft.

  • Beseitigt alle require-Anweisungen
  • Es werden nur die tatsächlich benötigten Skripte geladen
  • Verlangt keine strenge Namenskonvention für Verzeichnisse oder Dateien
  • Extrem schnell
  • Kein manuelles Aktualisieren des Caches, alles geschieht automatisch
  • Ausgereifte, stabile und weit verbreitete Bibliothek

Wir können also diese wohlbekannten Codeblöcke vergessen:

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

Installation

RobotLoader können Sie als einzelne eigenständige Datei RobotLoader.php herunterladen, mit require in Ihr Skript einbinden und sofort den komfortablen Autoload für die gesamte Anwendung genießen.

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

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

Wenn Sie eine Anwendung mit Composer bauen, können Sie ihn so installieren:

composer require nette/robot-loader

Verwendung

Ähnlich wie der Google-Robot Webseiten durchforstet und indexiert, durchläuft RobotLoader alle PHP-Skripte und notiert sich, welche Klassen, Interfaces, Traits und Enums er gefunden hat. Diese Erkenntnisse legt er anschließend im Cache ab und verwendet sie bei den folgenden Requests. Sie müssen nur angeben, welche Verzeichnisse er durchsuchen soll und wo er den Cache ablegen darf:

$loader = new Nette\Loaders\RobotLoader;

// Verzeichnisse, die RobotLoader indexieren soll (einschließlich Unterverzeichnisse)
$loader->addDirectory(__DIR__ . '/app');
$loader->addDirectory(__DIR__ . '/libs');

// Caching in das Verzeichnis 'temp' einstellen
$loader->setTempDirectory(__DIR__ . '/temp');
$loader->register(); // RobotLoader aktivieren

Und das ist alles! Von diesem Moment an müssen Sie require nicht mehr verwenden. Großartig!

Stößt RobotLoader beim Indexieren auf einen doppelten Klassennamen, wirft er eine Exception und macht Sie darauf aufmerksam. RobotLoader aktualisiert den Cache außerdem automatisch, wenn er eine Klasse laden soll, die er nicht kennt. Auf Produktionsservern empfehlen wir, das abzuschalten, siehe Caching.

Wenn RobotLoader bestimmte Verzeichnisse überspringen soll, verwenden Sie $loader->excludeDirectory('temp') (der Aufruf lässt sich mehrfach wiederholen, oder Sie übergeben mehrere Verzeichnisse).

Standardmäßig durchsucht RobotLoader nur Dateien mit der Endung .php. Sollen auch andere Dateitypen indexiert werden, passen Sie die Property $acceptFiles an, die ein Array von Masken enthält:

$loader->acceptFiles = ['*.php', '*.inc'];

Die Property $ignoreDirs enthält entsprechend die Masken der Verzeichnisse, die beim Durchsuchen immer übersprungen werden (standardmäßig .*, *.old, *.bak, *.tmp, temp).

Fehler in PHP-Dateien meldet RobotLoader standardmäßig, indem er eine ParseError-Exception wirft. Das lässt sich mit $loader->reportParseErrors(false) unterdrücken.

Unter der Haube hängt register() die Methode tryLoad() in die Autoload-Kette von PHP ein. Immer wenn PHP eine unbekannte Klasse, ein Interface, einen Trait oder ein Enum braucht, übergibt es den Namen an $loader->tryLoad($type), das die passende Datei findet und einbindet.

Nette Application

Innerhalb einer Nette Application, wo in der Startdatei Bootstrap.php das Objekt $configurator verwendet wird, lässt sich die Einrichtung vereinfachen:

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

Analysator für PHP-Dateien

RobotLoader lässt sich auch rein zum Auffinden von Klassen, Interfaces, Traits und Enums in PHP-Dateien verwenden, ohne die Autoload-Funktion zu nutzen:

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

// Durchsucht die Verzeichnisse nach Klassen/Interfaces/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. Er sorgt dafür, dass unveränderte Dateien nicht erneut durchsucht werden:

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

// Caching in das Verzeichnis 'temp' einstellen
$loader->setTempDirectory(__DIR__ . '/temp');

// Durchsucht die Verzeichnisse mit Hilfe des Caches
$loader->refresh();

// Gibt ein Array von Paaren Klasse => Dateiname zurück
$res = $loader->getIndexedClasses();

Caching

RobotLoader ist sehr schnell, weil er den Cache geschickt nutzt.

Während der Entwicklung nehmen Sie kaum wahr, dass er im Hintergrund läuft. Er aktualisiert seinen Cache fortlaufend und rechnet damit, dass Klassen und Dateien entstehen, gelöscht, umbenannt usw. werden können. Und er durchsucht keine Dateien erneut, die sich nicht geändert haben.

Auf einem Produktionsserver empfehlen wir umgekehrt, das Aktualisieren des Caches mit $loader->setAutoRefresh(false) abzuschalten (in einer Nette Application geschieht das automatisch), denn dort ändern sich die Dateien nicht. Zugleich ist es nötig, beim Hochladen einer neuen Version auf das Hosting den Cache zu löschen.

Das erste Durchsuchen der Dateien, wenn der Cache noch nicht existiert, kann bei größeren Anwendungen naturgemäß einen Moment dauern. RobotLoader hat eine eingebaute Vorbeugung gegen Cache Stampede. Das ist die Situation, in der eine große Zahl gleichzeitiger Requests auf dem Produktionsserver RobotLoader anstößt und, weil der Cache noch nicht existiert, alle mit dem Durchsuchen der Dateien beginnen würden, was den Server überlasten könnte. Zum Glück funktioniert RobotLoader so, dass bei mehreren gleichzeitigen Requests nur der erste Thread die Dateien indexiert und den Cache erzeugt, die übrigen warten und nutzen anschließend den erzeugten Cache.

PSR-4

Heutzutage lässt sich für das Autoloading Composer unter Einhaltung von PSR-4 verwenden. Vereinfacht gesagt handelt es sich um ein System, bei dem Namespaces und Klassennamen der Verzeichnisstruktur und den Dateinamen entsprechen, also etwa App\Core\RouterFactory in der Datei /path/to/App/Core/RouterFactory.php.

RobotLoader ist an keine feste Struktur gebunden und eignet sich deshalb für Situationen, in denen die Verzeichnisstruktur nicht genau den PHP-Namespaces entsprechen soll, oder bei der Entwicklung einer Anwendung, die solche Konventionen historisch nicht verwendet. Es ist auch möglich, beide Loader gemeinsam einzusetzen.

Wenn Sie auf eine neuere Version aktualisieren, sehen Sie sich die Seite Upgrade an.

Version: 4.x