Tricks für Laravel Eloquent Relationships

Eine Stärke von Laravel ist die elegante Syntax. Hat man in Laravel (durch sehr viele Tabellen in der Datenbank) sehr viele Models und Relationships, kann das Traversieren aber doch oftmals in weniger elegantem Code enden. Im Laufe der Zeit haben sich für mich drei kleine Erweiterungen bewährt, die ich nachfolgend kurz vorstellen will. Dazu nutzen wir lediglich etwas Vererbung, magische Methoden und Custom Collections.


Zuerst legen wir ein neues Model unter app\ConvenienceModel.php an:

b45e29b9125c2ab565b5526442437686

Anschließend lassen wir alle Models von unserem neuen ConvenienceModel erben:

b45e29b9125c2ab565b5526442437686

Eigene Funktionen mit Relationships mischen

Will man verbundene Models erhalten, nutzt man zum Aufruf die Standardsyntax:

b45e29b9125c2ab565b5526442437686

Fügt man nun eigene Business Logic hinzu, verwendet man gerne die (Lower) Camel Case Notation:

b45e29b9125c2ab565b5526442437686

Wir wollen die Syntax beider Varianten vereinheitlichen. Dazu fügen wir zum ConvenienceModel die magische Methode __call hinzu:

b45e29b9125c2ab565b5526442437686

Damit ist beispielsweise im oberen Beispiel auch dieser Aufruf möglich:

b45e29b9125c2ab565b5526442437686

Leere Objekte prüfen

Will man zu einer Personenaddresse den Namen des Landes ausgeben, sieht man oft den folgenden Code:

b45e29b9125c2ab565b5526442437686

Um das zu verhindern, binden wir die Library stringhelper ein und lassen bei einem nicht gefundenen Model eine spezielles Objekt der leeren Klasse empty zurückgeben:

b45e29b9125c2ab565b5526442437686

Damit gelingt auch der Aufruf (in diesem Beispiel wird im Falle, das etwas gefunden wird, wird der Name des Landes ausgegeben, in allen anderen Fällen ein leerer String).

b45e29b9125c2ab565b5526442437686

Wollen wir auch den Fall abdecken, dass der User mit der ID 42 möglicherweise gar nicht existiert, bauen wir uns hierfür ebenfalls eine kleine Helper-Funktion:

b45e29b9125c2ab565b5526442437686

Damit liefert der folgende Aufruf auch dann einen leeren String, wenn der User überhaupt nicht existiert:

b45e29b9125c2ab565b5526442437686

n:m-Relationen bequem traversieren

Schließlich wollen wir noch folgenden Code vereinfachen:

b45e29b9125c2ab565b5526442437686

Dazu nutzen wir die Möglichkeit von Custom Collections. Wir erweitern zunächst das ConvenienceModel:

b45e29b9125c2ab565b5526442437686

Anschließend erstellen wir die Datei app\Helpers\ConvenienceCollection.php, die dafür sorgt, dass der Aufruf unbekannter Funktionen bei Collections die Funktion für allen Items der Collection ausführt:

b45e29b9125c2ab565b5526442437686

Damit können wir folgenden Code nutzen, um alle Namen aller Länder aller Adressen aller Eltern der Person auszugeben:

b45e29b9125c2ab565b5526442437686

Aber auch Aufrufe wie der folgende sind möglich:

b45e29b9125c2ab565b5526442437686

Sortieren nach mehreren Spalten

Folgender Aufruf sortiert lediglich nach location, obwohl das nicht wahrscheinlich gewünscht war:

b45e29b9125c2ab565b5526442437686

Um das Sortieren nach mehreren Spalten zu ermöglichen, erweitern wir unsere ConvenienceCollection:

b45e29b9125c2ab565b5526442437686

Damit können wir dann die Collection auch nach mehreren Spalten sortieren mit:

b45e29b9125c2ab565b5526442437686

Standardsortierung

Wir erweitern die ConvenienceCollection um eine weitere Hilfsfunktion:

b45e29b9125c2ab565b5526442437686

Nun kann man jedem Model auch eine individuelle Standardsortierungsfunktion mitgeben:

b45e29b9125c2ab565b5526442437686

Damit können wir eine Collection sortieren mit:

b45e29b9125c2ab565b5526442437686

Objektbezeichnungen

Jedes Model implementiert die Methode getLabel (getName variiert je nach Model):

b45e29b9125c2ab565b5526442437686

Damit kann man schnell und einfach den Namen eines Objekts ausgeben. Anschließend kann man in der ConvenienceCollection noch die Helper-Methode sortByLabel implementieren:

b45e29b9125c2ab565b5526442437686

Leere Resultate

Ist ein Zwischenschritt leer, liefern die Laravel-Funktionen first() und last() normalerweise null zurück. Deshalb führen wir getFirst() und getLast() ein, sodass folgender Aufruf immer gelingt:

b45e29b9125c2ab565b5526442437686

Hiermit liefern wir einen __empty_helper zurück, den __x erkennt:

b45e29b9125c2ab565b5526442437686

Zurück