Über diese Seite
Unter Grundlagen der Paketentwicklung haben wir vorgestellt, dass Service Provider und Facades automatisch registriert werden, sobald Sie den Abschnittextra.laravel in der composer.json angeben. Auf dieser Seite erläutern wir die Interna dahinter, konkret die Funktionsweise der Klasse Illuminate\Foundation\PackageManifest auf Quellcode-Ebene.
Diese Seite ist die Ergänzung zu Grundlagen der Paketentwicklung. Wir empfehlen, die Grundlagen der automatischen Erkennung zuerst zu lesen.
Gesamtüberblick zur automatischen Erkennung
Die Klasse PackageManifest
Der Kern der automatischen Erkennung ist Illuminate\Foundation\PackageManifest. Nachfolgend eine Zusammenfassung der Implementierung zum Zeitpunkt von Framework 13.x.
- Das Manifest wird nach dem ersten Laden im Speicher zwischengespeichert (Property
$this->manifest). Wennproviders()innerhalb eines Requests mehrfach aufgerufen wird, entsteht nur ein einziger Datei-I/O. build()wird ausschließlich dann ausgeführt, wenn die Manifest-Datei nicht existiert. Im normalen Betrieb wird das Manifest also nicht bei jedem Aufruf neu gebaut.- Die tatsächliche Datei ist eine schlichte PHP-Datei, die ein Array
returnt (bootstrap/cache/packages.php) — das schnellstmögliche Format, darequiregenügt.
Bau des Manifests
Die Methodebuild() ist der Teil, der die Informationen aus der composer.json tatsächlich zusammenträgt.
composer.json direkt geparst wird, sondern vendor/composer/installed.json gelesen wird. Diese Datei wird von Composer bei composer install bzw. composer update erzeugt und enthält die Metadaten aller installierten Pakete. Da die Abschnitte extra aus den composer.json-Dateien der einzelnen Pakete hier gebündelt sind, greift Laravel ausschließlich auf die von Composer verwalteten Informationen zurück.
installed.json ist üblicherweise in .gitignore enthalten, daher funktioniert die automatische Erkennung beim initialen Setup (wenn noch kein vendor/ existiert) nicht. Der Cache wird erst nach Abschluss von composer install aufgebaut.Zwei Schreibweisen für dont-discover
dont-discover kann sowohl in der composer.json eines Pakets als auch der Anwendung stehen, hat aber unterschiedliche Bedeutungen.
composer.json auf Paketseite
composer.json auf Anwendungsseite
build() zeigt, wird das Array $ignore per array_merge mit den configuration['dont-discover']-Einträgen jedes Pakets gefüllt. Technisch ist es somit auch möglich, dass ein Paket selbst „die automatische Erkennung seiner eigenen Abhängigkeiten deaktiviert” — etwa, wenn ein intern verwendetes Sub-Paket sonst doppelt registriert würde. In der Praxis wird jedoch meist auf Anwendungsseite deaktiviert.
* in dont-discover angeben
Enthält das von packagesToIgnore() zurückgegebene Array den Wert *, wird $ignoreAll = true — und damit die automatische Erkennung für sämtliche Pakete deaktiviert. Nützlich in CI- oder Testumgebungen, um den Overhead der automatischen Erkennung zu vermeiden, oder wenn Sie in bootstrap/providers.php alles vollständig manuell verwalten möchten.
Die Cache-Datei
getCachedPackagesPath() gibt die Umgebungsvariable APP_PACKAGES_CACHE zurück, falls gesetzt, andernfalls bootstrap/cache/packages.php.
returnt.
php artisan package:discover ablesen, welche Pakete erkannt wurden.
Wann der Cache neu aufgebaut wird
Illuminate\Foundation\ComposerScripts hängt sich in drei Composer-Events ein, die alle dieselbe Methode clearCompiled() aufrufen.
composer install, composer update oder composer dump-autoload ausführen — der Konfigurations-, Services- und Paket-Cache werden alle zusammen gelöscht. Beim nächsten Start von Laravel wird PackageManifest::build() ausgeführt und der Cache aus dem aktuellen Stand der installed.json neu erstellt.
Dies ist das Standardverhalten eines Laravel-Projekts, das über den Abschnitt scripts in der composer.json konfiguriert ist.
composer.json einer Laravel-App (Auszug)
Manueller Neuaufbau mit php artisan package:discover
Wenn der Cache veraltet ist oder Sie vendor/ verändert haben, ohne Composer zu benutzen, können Sie den Cache mit package:discover manuell neu aufbauen.
$manifest->build() auf und gibt das Ergebnis aus — eine spezifische Kommandologik gibt es kaum. In Situationen, in denen Composer-Events nicht ausgelöst werden (z. B. wenn Sie in der CI-Pipeline composer install --no-scripts verwenden), müssen Sie diesen Befehl explizit aufrufen.
Hinweise für das Deployment
Im Produktions-Deployment ist es üblich,composer install --no-dev --optimize-autoloader auszuführen. Fügen Sie jedoch --no-scripts hinzu, wird der Paket-Cache nicht aktualisiert. Es ist daher sicherer, Ihrem Deployment-Skript einen expliziten Neuaufbau hinzuzufügen.
package:discover vor config:cache aus. Wird der Konfigurations-Cache zuerst erstellt, werden nachträglich hinzugefügte Paketkonfigurationen (etwa die per mergeConfigFrom registrierten) möglicherweise nicht berücksichtigt.
Zusammenfassung
- Die automatische Erkennung basiert nicht auf dem statischen Inhalt der
composer.json, sondern aufvendor/composer/installed.json, das Composer erzeugt. - Das Ergebnis wird in
bootstrap/cache/packages.phpals reines PHP-Array zwischengespeichert und lässt sich mitrequireallein schnell laden. - Der Cache wird bei den Events
composer install/update/dump-autoloadautomatisch gelöscht und beim nächsten Start neu aufgebaut. - In Umgebungen, in denen Composer mit
--no-scriptsläuft, müssen Siephp artisan package:discoverexplizit aufrufen. - Mit
*indont-discoverlässt sich die automatische Erkennung insgesamt deaktivieren.
Verwandte Seiten
- Grundlagen der Paketentwicklung — Service Provider und die grundlegende Verwendung von
extra.laravel - Deferred Service Provider — Optimierung des Ladezeitpunkts erkannter Provider
- Paket-Tests mit Orchestra Testbench — Der eigene
package:discover-Befehl von Testbench