©Sergey Emelyanov 2025 | Alle Rechte vorbehalten
Laravel: Die Kehrseite der Popularität oder Worüber auf Konferenzen nicht gesprochen wird
Laravel ist ohne Zweifel eine der tragenden Säulen der modernen PHP-Entwicklung. Seine Popularität ist enorm, und das aus gutem Grund: eine niedrige Einstiegshürde, eine riesige Community, ein reichhaltiges Ökosystem und die Möglichkeit, sowohl einfache als auch mittelkomplexe Projekte schnell umzusetzen. Die Integration mit Inertia.js ist ein Kapitel für sich – sie ermöglicht es, relativ schmerzfrei SPAs zu erstellen und dabei alle Vorzüge des Fullstack-Ansatzes zu nutzen. Doch wie jede Technologie hat auch Laravel seine „Leichen im Keller“ – Aspekte, die besonders bei großen und langlebigen Projekten für erhebliche Kopfschmerzen sorgen können. Sprechen wir genauer darüber.
truncate
, das kaskadierend andere Tabellen in PostgreSQL betreffen konnte (Ticket #35157 auf GitHub). Lange Zeit weigerte sich Taylor, diesen Fehler zu beheben, und berief sich auf die Abwärtskompatibilität, obwohl das Problem nur einen Datenbanktreiber betraf und von einer globalen Abwärtskompatibilität keine Rede sein konnte.Dieses Führungsmodell stößt bei einem Teil der Nutzer auf Unmut, und ehrlich gesagt ist so etwas in anderen großen Open-Source-Projekten selten anzutreffen. Taylor selbst erwähnte in einem Interview, dass er einen PR ablehnen und die gleiche Funktionalität dann selbst implementieren könnte, einfach um besser zu verstehen, wie sie funktioniert. Ein solcher Ansatz untergräbt meiner Meinung nach den Geist von Open Source und mindert die Motivation der Entwickler, zum Projekt beizutragen.
Taylor widersetzte sich lange der Einführung eines solchen Mechanismus in den Kern und hielt ihn für überflüssig. Erst relativ kürzlich wurde die Möglichkeit eingeführt, eine SQL-Datei mit dem Datenbankschema zu generieren, die bei Migrationen anstelle der Ausführung aller alten Dateien verwendet wird. Aber erstens ist das nicht das Standardverhalten. Zweitens funktioniert es nicht so reibungslos wie in anderen Frameworks: Nach dem Erstellen einer Migration wird das Schema nicht automatisch aktualisiert, es sind zusätzliche Schritte erforderlich. Dabei verlassen sich viele Bibliotheken und Entwicklungswerkzeuge für Autovervollständigung und Code-Analyse auf eine aktuelle Schemadatei. In CRM-Systemen, wo die Datenstruktur sehr verzweigt sein und sich häufig ändern kann, wird die Verwaltung einer solchen Menge an Migrationen zu einer echten Qual.
bootstrap/app.php
(in Versionen vor Laravel 11 war dies app/Http/Kernel.php
). Für eine kleine Anwendung – kein Problem. Sobald das Projekt jedoch wächst, wird diese Datei zu einer schwer lesbaren Liste. Wie wendet man Middleware auf eine bestimmte Route oder Routengruppe an? Das kann in den Dateien routes/web.php
oder routes/api.php
geschehen. Allerdings wird es sehr schwierig, die Gesamtstruktur der Middleware-Anwendung zu durchschauen und zu verstehen, welche Schicht wo verwendet wird. Die Datei bootstrap/app.php
(oder Kernel.php
) bietet zwar eine klarere Übersicht über die Gruppen, erlaubt aber nicht, Middleware einzelnen Routen mit derselben Flexibilität zuzuweisen.Neue Syntax in Laravel 11+ für bootstrap/app.php
:
->withMiddleware(function (Middleware $middleware) {
$middleware->appendToGroup('group-name', [
First::class,
Second::class,
]);
$middleware->prependToGroup('group-name', [
Third::class,
Fourth::class,
]);
})
Das verbessert die Situation für Gruppen zwar ein wenig, aber das grundlegende Problem der Lesbarkeit und des Managements von Schichten in großen Anwendungen bleibt bestehen. Fairerweise muss man sagen, dass in Symfony, wo es keine Middleware im eigentlichen Sinne gibt, sondern ein System aus Events und Listenern, die Logik der Anfrageverarbeitung noch undurchsichtiger und verwirrender sein kann.
Ja, dafür gibt es technische Gründe, und wer will, kann sich in die Feinheiten einarbeiten. Aber warum muss ich Zeit damit verbringen, die Caching-Besonderheiten des Frameworks selbst zu studieren, insbesondere in einer lokalen Umgebung? Ich erinnere mich an Tage, an denen ich stundenlang mit einem Problem gekämpft habe, das sich mit einem einzigen Befehl zum Löschen des Caches beheben ließ. Und es geht hier nicht um den Anwendungscache (Daten, die wir selbst cachen), sondern um den internen Cache des Frameworks – Konfigurationen, Routen, Views. Das Kernproblem ist, dass Laravel die Werte der Umgebungsvariablen (aus der .env-Datei) beim Ausführen von config:cache
zwischenspeichert. Dieser Ansatz ist nicht nur während der Entwicklung unpraktisch, sondern widerspricht auch den Prinzipien der Twelve-Factor App, die eine strikte Trennung von Konfiguration und Code vorschreiben.
lang/en/user.php
, lang/en/product.php
. Das ist sehr praktisch für große, mehrsprachige Projekte. Wenn man sich jedoch aus irgendeinem Grund für JSON-Dateien für Übersetzungen entscheidet (z. B. für ein einfacheres Parsen im Frontend), muss man damit rechnen, dass alle Schlüssel für eine Sprache in einer einzigen Datei liegen müssen (lang/en.json
). Die Möglichkeit, sie wie bei PHP-Dateien in logische Unterordner aufzuteilen, gibt es nicht. Das kann zu riesigen, schwer zu verwaltenden JSON-Dateien führen.User::create()
eine solche Methode hat, muss man ein spezielles Plugin installieren (z. B. Laravel Idea für PhpStorm), da die statische Methode create()
tatsächlich nicht in der Klasse User
vorhanden ist, sondern „magisch“ über eine Fassade weitergeleitet wird. Wenn man auf Plugins verzichten möchte, muss man ausführlichere Konstruktionen wie User::query()->create()
schreiben. Ähnlich verhält es sich mit der Autovervollständigung von Modellfeldern – ohne Plugins erkennt die IDE sie nicht.hasManyThrough
automatisch einzuprägen. Jedes Mal, wenn ich es verwenden muss, schaue ich in die Dokumentation. Warum man keine intuitivere Syntax machen konnte, zum Beispiel so etwas wie hasMany(Deployment::class)->through(IntermediateTable::class)->hasMany(Environment::class)
(ein übertriebenes Beispiel zur Veranschaulichung der Idee), bleibt mir ein Rätsel.strictMode
und preventAccessingMissingAttributes
(oder preventSilentlyDiscardingAttributes
in neueren Versionen) deaktiviert. Sie müssen explizit im Service Provider oder im Basismodell aktiviert werden. Leider sind diese Funktionen in vielen Projekten, die zur Wartung kommen, nicht aktiviert. Wozu führt das? Zu einem sehr merkwürdigen Verhalten, wenn man versehentlich auf eine nicht existierende Eigenschaft eines Modells zugreift oder versucht, einem nicht existierenden Attribut einen Wert zuzuweisen, und Laravel dies ohne Fehler oder Warnungen „schluckt“ (abhängig von der jeweiligen Option und Version). Das kann Fehler verschleiern und zu schwer zu debuggenden Problemen führen, besonders wenn man sich versehentlich beim Namen eines Feldes bei der Massenzuweisung von Attributen in einem CRM vertippt hat, wo Datengenauigkeit entscheidend ist.Trotz der genannten Nachteile war und ist Laravel ein mächtiges Werkzeug für die Webentwicklung. Seine Stärken überwiegen oft die Schwächen, insbesondere bei bestimmten Projekttypen. Es ist jedoch wichtig, auch die „Schattenseiten“ zu kennen, um auf mögliche Schwierigkeiten vorbereitet zu sein und fundierte Entscheidungen bei der Wahl des Technologie-Stacks oder bei der langfristigen Wartung eines Laravel-Projekts treffen zu können. Das Verständnis dieser Nuancen hilft Ihnen, qualitativ hochwertigeren Code zu schreiben und viele Fallstricke zu vermeiden.
©Sergey Emelyanov 2025 | Alle Rechte vorbehalten