Was ist ein Contract?
Die „Contracts” von Laravel sind ein Satz von Interfaces, die die Kernservices des Frameworks definieren. So beschreibt zum Beispiel der ContractIlluminate\Contracts\Queue\Queue die Methoden, die zum Einreihen von Jobs benötigt werden, und Illuminate\Contracts\Mail\Mailer die Methoden zum Versenden von E-Mails.
Für jeden Contract existiert eine entsprechende Implementierung im Framework. Laravel bringt beispielsweise Queue-Implementierungen für verschiedene Treiber sowie einen Mailer auf Basis des Symfony Mailers mit.
Alle Laravel-Contracts liegen in einem eigenen GitHub-Repository. Dieses dient als Schnellreferenz für alle verfügbaren Contracts und stellt ein einzelnes, entkoppeltes Paket dar, das Sie bei der Entwicklung von Paketen für die Zusammenarbeit mit Laravel-Services verwenden können.
Ein Contract ist nichts anderes als ein Interface. Er funktioniert exakt wie ein normales PHP-Interface. Laravel liefert die Implementierung dazu und injiziert sie über den Service Container.
Unterschied zwischen Contract und Facade
Facades und Helferfunktionen bieten einen bequemen Zugriff auf Laravel-Services, ohne dass Sie Contracts aus dem Service Container per Type-Hint auflösen müssen. In den meisten Fällen gibt es zu jeder Facade einen passenden Contract. Die wichtigsten Unterschiede zwischen Facades und Contracts:| Aspekt | Facade | Contract |
|---|---|---|
| Deklaration der Abhängigkeit | Nicht nötig (überall aufrufbar) | Explizit im Konstruktor |
| Testen | Mit shouldReceive() mocken | Mit üblichen Mocking-Bibliotheken ersetzen |
| Typischer Einsatz | Einfache Nutzung innerhalb der Anwendung | Paketentwicklung, explizites Abhängigkeitsmanagement |
| Lesbarkeit | Ein Import genügt | Abhängigkeiten sofort im Konstruktor sichtbar |
Wann sollten Sie Contracts einsetzen?
Ob Contract oder Facade – das ist eine Frage des persönlichen Stils bzw. der Teamvorlieben. Beide Ansätze ermöglichen robuste, testbare Laravel-Anwendungen. Contracts und Facades schließen sich nicht aus. Sie können in einem Teil der Anwendung Facades verwenden und in einem anderen auf Contracts setzen. Besonders sinnvoll sind Contracts in folgenden Fällen:- Wenn Sie ein Paket entwickeln, das mit mehreren PHP-Frameworks zusammenarbeitet – über das Paket
illuminate/contractskönnen Sie die Interaktion mit Laravel-Services definieren, ohne in Ihrercomposer.jsonkonkrete Laravel-Implementierungen zu fordern. - Wenn Sie Abhängigkeiten explizit machen möchten – anhand des Konstruktors ist auf einen Blick ersichtlich, wovon eine Klasse abhängt.
- Wenn Sie Implementierungen austauschen möchten – der Wechsel zu einer anderen Implementierung über den Service Container gelingt so besonders einfach.
Verwendung von Contracts
Wie bekommen Sie eine Contract-Implementierung? Ganz einfach. Viele Klassenarten in Laravel – Controller, Event Listener, Middleware, Queue-Jobs, Route-Closures – werden über den Service Container aufgelöst. Um eine Contract-Implementierung zu erhalten, geben Sie das Interface einfach als Type-Hint im Konstruktor der jeweiligen Klasse an. Sehen Sie sich zum Beispiel den folgenden Event Listener an.Eigene Contracts erstellen
Mit eigenen Contracts können Sie die Abhängigkeiten zwischen den Bestandteilen Ihrer Anwendung klar herausarbeiten.Im Service Provider binden
Verknüpfen Sie Contract und Implementierung in einem Service Provider.
Stripe auf einen anderen Anbieter umstellen, genügt eine Anpassung an einer einzigen Stelle – der Bindung. Die Controller-Logik bleibt unverändert.
Übersicht wichtiger Contracts
Ausschnitt einer Zuordnung häufig genutzter Contracts zu ihren Facades:| Contract | Facade |
|---|---|
Illuminate\Contracts\Auth\Access\Gate | Gate |
Illuminate\Contracts\Auth\Factory | Auth |
Illuminate\Contracts\Bus\Dispatcher | Bus |
Illuminate\Contracts\Cache\Factory | Cache |
Illuminate\Contracts\Cache\Repository | Cache::driver() |
Illuminate\Contracts\Config\Repository | Config |
Illuminate\Contracts\Console\Kernel | Artisan |
Illuminate\Contracts\Container\Container | App |
Illuminate\Contracts\Encryption\Encrypter | Crypt |
Illuminate\Contracts\Events\Dispatcher | Event |
Illuminate\Contracts\Filesystem\Factory | Storage |
Illuminate\Contracts\Filesystem\Filesystem | Storage::disk() |
Illuminate\Contracts\Hashing\Hasher | Hash |
Illuminate\Contracts\Mail\Mailer | Mail |
Illuminate\Contracts\Notifications\Dispatcher | Notification |
Illuminate\Contracts\Queue\Factory | Queue |
Illuminate\Contracts\Queue\Queue | Queue::connection() |
Illuminate\Contracts\Queue\ShouldQueue | — |
Illuminate\Contracts\Redis\Factory | Redis |
Illuminate\Contracts\Routing\ResponseFactory | Response |
Illuminate\Contracts\Routing\UrlGenerator | URL |
Illuminate\Contracts\Session\Session | Session::driver() |
Illuminate\Contracts\Translation\Translator | Lang |
Illuminate\Contracts\Validation\Factory | Validator |
Illuminate\Contracts\View\Factory | View |
Nächste Schritte
Facades
Vertiefen Sie die Funktionsweise von Facades und wie Sie sie testen.