Modellbeziehungen in Laravel Eloquent verstehen (2023)

Modelle und ihre Beziehungen sind das Herz von Laravel Eloquent. Wenn sie es Ihnen schwer machen oder Sie keinen einfachen, freundlichen und vollständigen Leitfaden finden, beginnen Sie hier!

Wenn der Autor auf der anderen Seite seines Programmierartikels sitzt, kann er die Aura des Fachwissens / Prestiges, die die Plattform bietet, leicht vortäuschen oder in die Luft jagen. Aber ich werde ehrlich sein - ich hatte eine äußerst schwere Zeit Laravel lernen, schon allein, weil es mein erstes Full-Stack-Framework war. Ein Grund war, dass ich es nicht bei der Arbeit benutzte und es aus Neugier erforschte; Also würde ich einen Versuch machen, zu einem Punkt kommen, verwirrt werden, aufgeben und schließlich alles vergessen. Ich muss das 5-6 Mal gemacht haben, bevor es für mich Sinn machte (natürlich hilft die Dokumentation nicht).

Aber was immer noch keinen Sinn ergab, war eloquent. Oder zumindest die Beziehungen zwischen Modellen (weil Eloquent zu groß ist, um vollständig zu lernen). Beispiele für das Modellieren von Autoren und Blog-Posts sind ein Witz, da echte Projekte weitaus komplexer sind. Leider verwenden die offiziellen Dokumente dieselben (oder ähnliche) Beispiele. Oder selbst wenn ich auf einen nützlichen Artikel / eine nützliche Ressource gestoßen bin, war die Erklärung so schlecht oder fehlte so sehr, dass sie einfach keinen Nutzen hatte.

Modellbeziehungen in Laravel Eloquent verstehen (1)

(Übrigens wurde ich schon einmal angegriffen, weil ich die offizielle Dokumentation angegriffen habe. Wenn Sie also ähnliche Ideen haben, ist hier meine Standardantwort: Schauen Sie sich die Django-Dokumentation an und sprechen Sie dann mit mir.)

Schließlich kam es Stück für Stück zusammen und ergab einen Sinn. Endlich konnte ich Projekte richtig modellieren und bequem nutzen. Dann stieß ich eines Tages auf einige nette Sammlungs-Tricks, die diese Arbeit angenehmer machen. In diesem Artikel möchte ich alles behandeln, angefangen bei den Grundlagen bis hin zu allen möglichen Anwendungsfällen, die in realen Projekten auftreten werden.

Warum sind eloquente Modellbeziehungen schwierig?

Leider stoße ich auf viel zu viele Laravel-Entwickler, die Modelle nicht richtig verstehen.

Aber warum?

Selbst heute, wenn es auf Laravel eine Explosion von Kursen, Artikeln und Videos gibt, ist das allgemeine Verständnis schlecht. Ich denke, es ist ein wichtiger Punkt und es lohnt sich, darüber nachzudenken.

Modellbeziehungen in Laravel Eloquent verstehen (2)

Wenn Sie mich fragen, werde ich sagen, dass eloquente Modellbeziehungen überhaupt nicht schwer sind. Zumindest aus der Perspektive der Definition von „hart“. Live-Schema-Migrationen sind schwierig. Das Schreiben einer neuen Template-Engine ist schwierig. Es ist schwierig, Code zum Kern von Laravel beizutragen. Im Vergleich dazu lernen und verwenden Sie ein ORM. . . Nun, das kann nicht schwer sein! 🤭🤭

Was tatsächlich passiert, ist das PHP-Entwickler lernen Laravel finde Eloquent schwer. Das ist das eigentliche Grundproblem, und meiner Meinung nach tragen mehrere Faktoren dazu bei (harte, unpopuläre Meinungswarnung!):

  • Vor Laravel war CodeIgniter (es ist immer noch so) für die meisten PHP-Entwickler ein Framework lebendigübrigens, auch wenn es mehr Laravel / CakePHP-artig geworden ist). In der älteren CodeIgniter-Community (falls vorhanden) bestand die „Best Practice“ darin, SQL-Abfragen bei Bedarf direkt zu speichern. Und obwohl wir heute einen neuen CodeIgniter haben, haben sich die Gewohnheiten übernommen. Als Ergebnis, wenn Laravel lernenist die Idee eines ORM für PHP-Entwickler 100% neu.
  • Wenn Sie den sehr geringen Prozentsatz von PHP verwerfen, der Frameworks wie Yii, CakePHP usw. ausgesetzt ist, sind die übrigen daran gewöhnt, in Kern-PHP oder in einer Umgebung wie WordPress zu arbeiten. Und auch hier gibt es keine OOP-basierte Denkweise, also ein Framework, einen Service-Container, ein Entwurfsmuster, ein ORM. . . Das sind fremde Konzepte.
  • In der PHP-Welt gibt es kaum ein Konzept für kontinuierliches Lernen. Der durchschnittliche Entwickler arbeitet gerne mit Einzelserver-Setups, die relationale Datenbanken verwenden und als Zeichenfolgen geschriebene Abfragen ausgeben. Asynchrone Programmierung, Web-Sockets, HTTP 2/3, Linux (Docker vergessen), Unit-Tests, Domain-Driven Design - all dies sind fremde Ideen für einen überwältigenden Anteil der PHP-Entwickler. Infolgedessen passiert es nicht, wenn man auf etwas Neues und Herausforderndes liest, bis man es für angenehm hält, wenn man auf Eloquent trifft.
  • Das allgemeine Verständnis von Datenbanken und Modellierung ist ebenfalls schlecht. Da das Datenbankdesign direkt und untrennbar mit Eloquent-Modellen verbunden ist, wird der Schwierigkeitsgrad höher.

Ich will nicht hart sein und global verallgemeinern - das gibt esAusgezeichnet Auch PHP-Entwickler und viele von ihnen, aber ihr Gesamtprozentsatz ist sehr niedrig.

Wenn Sie dies lesen, bedeutet dies, dass Sie alle diese Barrieren überwunden haben, auf Laravel gestoßen sind und sich mit Eloquent angelegt haben.

Herzliche Glückwünsche! 👏

Du bist fast da. Alle Bausteine ​​sind vorhanden und wir müssen sie nur in der richtigen Reihenfolge und im richtigen Detail durchgehen. Mit anderen Worten, beginnen wir auf Datenbankebene.

Datenbankmodelle: Beziehungen und Kardinalität

Nehmen wir zur Vereinfachung an, wir arbeiten mit relationale Datenbanken nur in diesem Artikel. Ein Grund dafür ist, dass ORMs ursprünglich für relationale Datenbanken entwickelt wurden. Der andere Grund ist, dass RDBMS immer noch sehr beliebt sind.

Datenmodell

Lassen Sie uns zunächst die Datenmodelle besser verstehen. Die Idee eines Modells (oder eines technische Daten Modell, genauer gesagt), stammt aus der Datenbank. Keine Datenbank, keine Daten und somit kein Datenmodell. Und was ist ein Datenmodell? Ganz einfach, so entscheiden Sie sich, Ihre Daten zu speichern / strukturieren. In einem E-Commerce-Geschäft können Sie beispielsweise alles in einem riesigen Tisch speichern (SCHRECKLICHE Praxis, aber leider nicht ungewöhnlich in der PHP-Welt). das wäre dein Datenmodell. Sie können die Daten auch in 20 Haupt- und 16 Verbindungstabellen aufteilen. Das ist auch ein Datenmodell.

Beachten Sie außerdem, dass die Struktur der Daten in der Datenbank nicht zu 100% mit der Anordnung im ORM des Frameworks übereinstimmen muss. Es ist jedoch immer wichtig, die Dinge so nah wie möglich zu halten, damit wir bei der Entwicklung nicht mehr auf eines achten müssen.

Kardinalität

Lassen Sie uns diesen Begriff auch schnell aus dem Weg räumen: Kardinalität. Es bezieht sich nur auf "zählen", lose gesprochen. Also 1, 2, 3. . . kann alles die Kardinalität von etwas sein. Ende der Geschichte. Lass uns in Bewegung bleiben!

Beziehungen

Wenn wir jetzt Daten in einem beliebigen Systemtyp speichern, gibt es Möglichkeiten, wie Datenpunkte miteinander in Beziehung gesetzt werden können. Ich weiß, das klingt abstrakt und langweilig, aber ertrage es ein wenig mit mir. Die Art und Weise, wie verschiedene Datenelemente verbunden sind, wird als bezeichnetBeziehungen. Schauen wir uns zunächst einige Beispiele an, die keine Datenbank sind, damit wir davon überzeugt sind, dass wir die Idee vollständig verstehen.

  • Wenn wir alles in einem Array speichern, ist eines möglich Beziehung ist: Das nächste Datenelement befindet sich an einem Index, der größer ist als der vorherige Index um 1.
  • Wenn wir Daten in einem Binärbaum speichern, besteht eine mögliche Beziehung darin, dass der untergeordnete Baum links immer kleinere Werte als der übergeordnete Knoten hat (wenn wir den Baum auf diese Weise beibehalten möchten).
  • Wenn wir Daten als Array von Arrays gleicher Länge speichern, können wir eine Matrix nachahmen, und dann werden ihre Eigenschaften zu den Beziehungen für unsere Daten.

Wir sehen also, dass das Wort „Beziehung“ im Kontext von Daten keine feste Bedeutung hat. Wenn zwei Personen dieselben Daten betrachten, identifizieren sie möglicherweise zwei sehr unterschiedliche Datenbeziehungen (Hallo, Statistiken!), Und beide können gültig sein.

Relational Datenbanken

Basierend auf all den Begriffen, die wir bisher besprochen haben, können wir endlich über etwas sprechen, das einen direkten Link zu Modellen in einem Webframework (Laravel) hat - relationale Datenbanken. Für die meisten von uns wird als primäre Datenbank MySQL, MariaDB, PostgreSQL, MSSQL, SQL Server, SQLite oder ähnliches verwendet. Wir wissen vielleicht auch vage, dass diese als RDBMS bezeichnet werden, aber die meisten von uns haben vergessen, was es tatsächlich bedeutet und warum es wichtig ist.

Das "R" in RDBMS steht natürlich für Relational. Dies ist kein willkürlich gewählter Begriff; Auf diese Weise unterstreichen wir die Tatsache, dass diese Datenbanksysteme so konzipiert sind, dass sie effizient mit den Beziehungen zwischen gespeicherten Daten arbeiten. Tatsächlich hat „Beziehung“ hier eine strenge mathematische Bedeutung, und obwohl sich kein Entwickler darum kümmern muss, hilft es zu wissen, dass es eine strenge Mathematik gibt Stiftung unter diesen Arten von Datenbanken.

Entdecken Sie diese Ressourcen zu lerne SQL und NoSQL.

(Video) Laravel Filament Admin Panel: [4] Rollen- und Beziehungsmanager

Okay, wir wissen aus Erfahrung, dass Daten in RDBMS als Tabellen gespeichert werden. Wo sind dann die Beziehungen?

Arten von Beziehungen in RDBMS

Dies ist vielleicht der wichtigste Teil des gesamten Themas Laravel und Modellbeziehungen. Wenn Sie dies nicht verstehen, wird Eloquent niemals einen Sinn ergeben. Achten Sie daher in den nächsten Minuten darauf (es ist nicht einmal so schwierig).

Ein RDBMS erlaubt uns Beziehungen zwischen Daten zu haben - auf Datenbankebene. Dies bedeutet, dass diese Beziehungen nicht unpraktisch / imaginär / subjektiv sind und von verschiedenen Personen mit demselben Ergebnis erstellt oder abgeleitet werden können.

Gleichzeitig gibt es in einem RDBMS bestimmte Funktionen / Tools, mit denen wir diese Beziehungen erstellen und erzwingen können, z.

  • Primärschlüssel
  • Unbekannter Schlüssel
  • Einschränkungen

Ich möchte nicht, dass dieser Artikel zu einem Kurs in Datenbanken wird, daher gehe ich davon aus, dass Sie diese Konzepte kennen. Wenn nicht, oder falls Sie sich in Ihrem Selbstvertrauen wackelig fühlen, empfehle ich dieses freundliche Video (zögern Sie nicht, die gesamte Serie zu erkunden):

Zufällig sind diese Beziehungen im RDBMS-Stil auch die häufigsten, die in realen Anwendungen auftreten (nicht immer, da ein soziales Netzwerk am besten als Grafik und nicht als Sammlung von Tabellen modelliert werden kann). Schauen wir sie uns also einzeln an und versuchen auch zu verstehen, wo sie nützlich sein könnten.

Eins-zu-eins-Beziehung

In fast jeder Webanwendung gibt es Benutzerkonten. Außerdem gilt (im Allgemeinen) Folgendes für die Benutzer und Konten:

  • Ein Benutzer kann nur ein Konto haben.
  • Ein Konto kann nur einem Benutzer gehören.

Ja, wir können argumentieren, dass sich eine Person mit einer anderen E-Mail anmelden und somit zwei Konten erstellen kann. Aus Sicht der Webanwendung sind dies jedoch zwei verschiedene Personen mit zwei verschiedenen Konten. Die Anwendung zeigt beispielsweise nicht die Daten eines Kontos in einem anderen an.

All diese Haarspalterei bedeutet: Wenn Sie in Ihrer Anwendung eine solche Situation haben und eine relationale Datenbank verwenden, müssen Sie diese als Eins-zu-Eins-Beziehung entwerfen. Beachten Sie, dass Sie niemand künstlich zwingt - es gibt eine klare Situation im Geschäftsbereichund Sie verwenden zufällig eine relationale Datenbank. . . Nur wenn beide Bedingungen erfüllt sind, erreichen Sie eine Eins-zu-Eins-Beziehung.

In diesem Beispiel (Benutzer und Konten) können wir diese Beziehung beim Erstellen des Schemas wie folgt implementieren:

CREATE TABLE users( id INT NOT NULL AUTO_INCREMENT, email VARCHAR(100) NOT NULL, password VARCHAR(100) NOT NULL, PRIMARY KEY(id));CREATE TABLE accounts( id INT NOT NULL AUTO_INCREMENT, role VARCHAR(50) NOT NULL, PRIMARY KEY(id), FOREIGN KEY(id) REFERENCES users(id));

Beachten Sie den Trick hier? Es ist ziemlich ungewöhnlich, wenn Apps im Allgemeinen erstellt werden, aber in der accounts Tabelle haben wir das Feld id sowohl als Primärschlüssel als auch als Fremdschlüssel eingestellt! Die Fremdschlüsseleigenschaft verknüpft sie mit dem users Tabelle (natürlich 🙄), während die Primärschlüsseleigenschaft die id Spalte einzigartig - eine echte Eins-zu-Eins-Beziehung!

Zugegeben, die Treue dieser Beziehung ist nicht garantiert. Zum Beispiel hindert mich nichts daran, 200 neue Benutzer hinzuzufügen, ohne einen einzigen Eintrag zum hinzuzufügen accounts Tabelle. Wenn ich das mache, bekomme ich eine Eins-zu-Null Beziehung! 🤭🤭 Aber im Rahmen der reinen Struktur ist das das Beste, was wir tun können. Wenn wir verhindern möchten, dass Benutzer ohne Konten hinzugefügt werden, müssen wir Hilfe von einer Art Programmierlogik in Anspruch nehmen, entweder in Form von Datenbank-Triggern oder von Laravel erzwungenen Validierungen.

Modellbeziehungen in Laravel Eloquent verstehen (4)

Wenn Sie anfangen, Stress abzubauen, habe ich einige sehr gute Ratschläge:

  • Mach langsam. So langsam wie nötig. Anstatt zu versuchen, diesen Artikel und die 15 anderen, die Sie heute mit einem Lesezeichen versehen haben, zu beenden, bleiben Sie bei diesem. Lassen Sie es 3, 4, 5 Tage dauern, wenn es das ist - Ihr Ziel sollte es sein, eloquente Modellbeziehungen für immer von Ihrer Liste zu streichen. Sie sind schon einmal von Artikel zu Artikel gesprungen und haben mehrere hundert Stunden verschwendet, aber es hat nicht geholfen. Also mach diesmal etwas anderes. 😇
  • Während dieser Artikel über Laravel Eloquent handelt, kommt alles viel später. Die Grundlage des Ganzen ist das Datenbankschema, daher sollte unser Fokus darauf liegen, dies zuerst richtig zu machen. Wenn Sie nicht nur auf Datenbankebene arbeiten können (vorausgesetzt, es gibt keine Frameworks auf der Welt), sind Modelle und Beziehungen niemals sinnvoll. Also vergiss Laravel fürs Erste. Vollständig. Wir sprechen vorerst nur über Datenbankdesign und machen es. Ja, ich mache ab und zu Laravel-Referenzen, aber Ihre Aufgabe ist es, sie vollständig zu ignorieren, wenn sie das Bild für Sie komplizieren.
  • Lesen Sie später etwas mehr über Datenbanken und deren Angebot. Indizes, Leistung, Trigger, zugrunde liegende Datenstrukturen und deren Verhalten, Caching, Beziehungen in MongoDB. . . Welche tangentialen Themen Sie auch behandeln können, hilft Ihnen als Ingenieur. Denken Sie daran, Framework-Modelle sind nur Geister-Shells. Die eigentliche Funktionalität einer Plattform beruht auf den zugrunde liegenden Datenbanken.

Eins-zu-viele-Beziehung

Ich bin mir nicht sicher, ob Sie das erkannt haben, aber dies ist die Art von Beziehung, die wir alle intuitiv in unserer täglichen Arbeit herstellen. Wenn wir eine erstellen orders Tabelle (ein hypothetisches Beispiel), um beispielsweise einen Fremdschlüssel für die zu speichern users Tabelle erstellen wir eine Eins-zu-Viele-Beziehung zwischen Benutzern und Bestellungen. Warum das? Betrachten Sie es noch einmal aus der Perspektive, wer wie viele haben kann: Ein Benutzer darf mehr als eine Bestellung haben, so funktioniert der gesamte E-Commerce. Und von der anderen Seite gesehen besagt die Beziehung, dass eine Bestellung nur einem Benutzer gehören kann, was ebenfalls sehr sinnvoll ist.

In der Datenmodellierung, in RDBMS-Büchern und in der Systemdokumentation wird diese Situation schematisch wie folgt dargestellt:

Modellbeziehungen in Laravel Eloquent verstehen (5)

Beachten Sie die drei Linien, die eine Art Dreizack bilden? Dies ist das Symbol für „viele“. In diesem Diagramm wird also angegeben, dass ein Benutzer viele Bestellungen haben kann.

Übrigens sind diese „vielen“ und „eins“ Zählungen, denen wir wiederholt begegnen, die sogenannte Kardinalität einer Beziehung (erinnern Sie sich an dieses Wort aus einem vorherigen Abschnitt?). Auch für diesen Artikel hat der Begriff keine Verwendung, aber es hilft, das Konzept zu kennen, falls es während eines Interviews oder einer weiteren Lektüre auftaucht.

Einfach, oder? In Bezug auf die tatsächliche SQL ist das Erstellen dieser Beziehung ebenfalls einfach. In der Tat ist es viel einfacher als im Fall einer Eins-zu-Eins-Beziehung!

CREATE TABLE users( id INT NOT NULL AUTO_INCREMENT, email VARCHAR(100) NOT NULL, password VARCHAR(100) NOT NULL, PRIMARY KEY(id) );CREATE TABLE orders( id INT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, description VARCHAR(50) NOT NULL, PRIMARY KEY(id), FOREIGN KEY(user_id) REFERENCES users(id) );

Die orders In der Tabelle werden Benutzer-IDs für jede Bestellung gespeichert. Da es keine Einschränkung (Einschränkung) gibt, dass die Benutzer-IDs in der orders Tabelle muss eindeutig sein, das heißt, wir können eine einzelne ID viele Male wiederholen. Dies schafft die Eins-zu-Viele-Beziehung und nicht irgendeine arkane Magie, die darunter verborgen ist. Die Benutzer-IDs werden irgendwie dumm in der gespeichert orders Tabelle, und SQL hat kein Konzept von Eins-zu-Viele, Eins-zu-Eins usw. Aber sobald wir Daten auf diese Weise speichern, können wirthink von einer Eins-zu-Viele-Beziehung.

Modellbeziehungen in Laravel Eloquent verstehen (6)

Hoffentlich macht es jetzt Sinn. Oder zumindest sinnvoller als zuvor. 😅 Denken Sie daran, dass dies wie alles andere nur eine Frage der Übung ist. Wenn Sie dies in realen Situationen 4-5 Mal getan haben, werden Sie nicht einmal mehr darüber nachdenken.

Viele-zu-viele-Beziehungen

Die nächste Art von Beziehung, die in der Praxis entsteht, ist die sogenannte Viele-zu-Viele-Beziehung. Bevor wir uns über Frameworks Gedanken machen oder sogar in Datenbanken eintauchen, sollten wir uns noch einmal ein reales Analogon vorstellen: Bücher und Autoren. Denken Sie an Ihren Lieblingsautor. Sie haben mehr als ein Buch geschrieben, oder? Gleichzeitig ist es ziemlich üblich, dass mehrere Autoren an einem Buch zusammenarbeiten (zumindest im Sachbuch-Genre). Ein Autor kann also viele Bücher schreiben, und viele Autoren können ein Buch schreiben. Zwischen den beiden Entitäten (Buch und Autor) bildet sich eine Viele-zu-Viele-Beziehung.

(Video) Laravel E-Commerce: [36] Filament-Admin-Panel

Angesichts der Tatsache, dass es sehr unwahrscheinlich ist, dass Sie eine reale App mit Bibliotheken oder Büchern und Autoren erstellen, sollten wir uns einige weitere Beispiele überlegen. In einer B2B-Einstellung bestellt ein Hersteller Artikel bei einem Lieferanten und erhält wiederum eine Rechnung. Die Rechnung enthält mehrere Werbebuchungen, in denen jeweils die gelieferte Menge und der gelieferte Artikel aufgeführt sind. Zum Beispiel 5-Zoll-Rohrstücke x 200 usw. In dieser Situation haben Artikel und Rechnungen eine Viele-zu-Viele-Beziehung (denken Sie darüber nach und überzeugen Sie sich selbst). In einem Flottenmanagementsystem haben Fahrzeuge und Fahrer eine ähnliche Beziehung. Auf einer E-Commerce-Website können Benutzer und Produkte eine Viele-zu-Viele-Beziehung haben, wenn wir Funktionen wie Favoriten oder Wunschzettel berücksichtigen.

Fair genug, wie kann man nun diese Viele-zu-Viele-Beziehung in SQL erstellen? Aufgrund unseres Wissens darüber, wie die Eins-zu-Viele-Beziehung funktioniert, könnte es verlockend sein zu glauben, wir sollten Fremdschlüssel für die andere Tabelle in beiden Tabellen speichern. Wenn wir dies versuchen, stoßen wir jedoch auf große Probleme. Schauen Sie sich dieses Beispiel an, in dem Bücher Autoren sind, die eine Viele-zu-Viele-Beziehung haben sollen:

Modellbeziehungen in Laravel Eloquent verstehen (7)

Auf den ersten Blick sieht alles gut aus - Bücher werden den Autoren genau auf viele-zu-viele-Arten zugeordnet. Aber schauen Sie sich das genau an authors Tabellendaten: Die Buch-IDs 12 und 13 stammen beide von Peter M. (Autoren-ID 2), weshalb wir keine andere Wahl haben, als die Einträge zu wiederholen. Nicht nur das authors Tabelle haben jetzt Datenintegritätsprobleme (richtig Normalisierung und das alles), die Werte in der id Spalte wiederholen sich jetzt. Dies bedeutet, dass es in dem von uns ausgewählten Design keine Primärschlüsselspalte geben kann (da Primärschlüssel keine doppelten Werte haben können) und alles auseinander fällt.

Modellbeziehungen in Laravel Eloquent verstehen (8)

Natürlich brauchen wir dafür einen neuen Weg, und zum Glück ist dieses Problem bereits gelöst. Da das Speichern von Fremdschlüsseln direkt in beiden Tabellen die Dinge durcheinander bringt, besteht die richtige Möglichkeit, in RDBMS viele-zu-viele-Beziehungen herzustellen, darin, eine sogenannte „Verbindungstabelle“ zu erstellen. Die Idee ist im Grunde, die beiden ursprünglichen Tabellen ungestört stehen zu lassen und eine dritte Tabelle zu erstellen, um die Viele-zu-Viele-Zuordnung zu demonstrieren.

Lassen Sie uns das fehlgeschlagene Beispiel wiederholen, um eine Verknüpfungstabelle zu enthalten:

Modellbeziehungen in Laravel Eloquent verstehen (9)

Beachten Sie, dass es drastische Änderungen gegeben hat:

  • Die Anzahl der Spalten in der authors Tisch ist reduziert.
  • Die Anzahl der Spalten in der books Tisch ist reduziert.
  • Die Anzahl der Zeilen in der authors Tabelle wird reduziert, da keine Wiederholung mehr erforderlich ist.
  • Eine neue Tabelle namens authors_books ist erschienen und enthält Informationen darüber, welche Autoren-ID mit welcher Buch-ID verbunden ist. Wir hätten die Verknüpfungstabelle beliebig benennen können, aber gemäß Konvention ist dies das Ergebnis der einfachen Verknüpfung der beiden Tabellen, die sie darstellt, mit einem Unterstrich.

Die Verknüpfungstabelle hat keinen Primärschlüssel und enthält in den meisten Fällen nur zwei Spalten - IDs aus den beiden Tabellen. Es ist fast so, als hätten wir die Fremdschlüsselspalten aus unserem früheren Beispiel entfernt und in diese neue Tabelle eingefügt. Da es keinen Primärschlüssel gibt, kann es so viele Wiederholungen geben, wie zum Aufzeichnen aller Beziehungen erforderlich sind.

Jetzt können wir mit unseren Augen sehen, wie die Verknüpfungstabelle die Beziehungen klar anzeigt, aber wie greifen wir in unseren Anwendungen darauf zu? Das Geheimnis ist mit dem Namen verbunden - Beitritt Tabelle. Dies ist kein Kurs zu SQL-Abfragen, daher werde ich nicht darauf eingehen. Wenn Sie jedoch alle Bücher eines bestimmten Autors in einer effizienten Abfrage haben möchten, verbinden Sie die Tabellen in derselben Reihenfolge mit SQL -> authors, authors_books und booksdem „Vermischten Geschmack“. Seine authors und authors_books Tabellen werden über die verbunden id und author_id Spalten, während die authors_books und books Tabellen werden auf dem verbunden book_id und id Spalten.

Modellbeziehungen in Laravel Eloquent verstehen (10)

Erschöpfend, ja. Aber schauen Sie sich die gute Seite an - wir sind fertigAlle die notwendige Theorie / Grundlagen, die wir tun mussten, bevor wir uns mit eloquenten Modellen befassten. Und ich möchte Sie daran erinnern, dass all dieses Zeug nicht optional ist! Wenn Sie das Datenbankdesign nicht kennen, bleiben Sie für immer im Land der eloquenten Verwirrung. Unabhängig davon, was Eloquent tut oder versucht, spiegelt es diese Details auf Datenbankebene perfekt wider, sodass leicht zu erkennen ist, warum der Versuch, Eloquent zu lernen, während man vor RDBMS davonläuft, eine sinnlose Übung ist.

Creating model relationships in Laravel Eloquent

Nach einem Umweg, der ungefähr 70,000 Meilen dauerte, haben wir endlich den Punkt erreicht, an dem wir über Eloquent, seine Modelle und deren Erstellung / Verwendung sprechen können. Jetzt haben wir im vorherigen Teil des Artikels erfahren, dass alles mit der Datenbank beginnt und wie Sie Ihre Daten modellieren. Dadurch wurde mir klar, dass ich ein einziges vollständiges Beispiel verwenden sollte, um ein neues Projekt zu starten. Gleichzeitig möchte ich, dass dieses Beispiel real ist und nicht Blogs und Autoren oder Bücher und Regale (die ebenfalls real sind, aber zu Tode gebracht wurden).

Stellen wir uns ein Geschäft vor, das Stofftiere verkauft. Nehmen wir außerdem an, dass uns das Anforderungsdokument bereitgestellt wurde, anhand dessen wir diese vier Entitäten im System identifizieren können: Benutzer, Bestellungen, Rechnungen, Artikel, Kategorien, Unterkategorien und Transaktionen. Ja, es wird wahrscheinlich mehr Komplikationen geben, aber lassen Sie uns das einfach beiseite legen und uns darauf konzentrieren, wie wir von einem Dokument zu einer App gelangen.

Sobald die Hauptentitäten im System identifiziert wurden, müssen wir uns überlegen, wie sie sich in Bezug auf die Datenbankbeziehungen, die wir bisher besprochen haben, zueinander verhalten. Hier sind die, an die ich denken kann:

  • Benutzer und Bestellungen: Eins zu viele.
  • Bestellungen und Rechnungen: Eins zu eins. Mir ist klar, dass dieser nicht geschnitten und getrocknet ist, und je nach Geschäftsbereich kann es eine Eins-zu-Viele-, eine Viele-zu-Eins- oder eine Viele-zu-Viele-Beziehung geben. Bei einem durchschnittlichen kleinen E-Commerce-Geschäft führt eine Bestellung jedoch nur zu einer Rechnung und umgekehrt.
  • Bestellungen und Artikel: Viele zu viele.
  • Artikel und Kategorien: Viele zu einem. Auch dies ist bei großen E-Commerce-Websites nicht der Fall, aber wir haben einen kleinen Betrieb.
  • Kategorien und Unterkategorien: eins zu viele. Auch hier finden Sie die meisten Beispiele aus der Praxis, die dem widersprechen, aber hey, Eloquent ist schon schwer genug, also machen wir die Datenmodellierung nicht schwieriger!
  • Bestellungen und Transaktionen: Eins zu viele. Ich möchte diese beiden Punkte auch als Begründung für meine Wahl hinzufügen: 1) Wir hätten auch eine Beziehung zwischen Transaktionen und Rechnungen hinzufügen können. Es ist nur eine Entscheidung zur Datenmodellierung. 2) Warum eins zu viele hier? Nun, es ist üblich, dass eine Auftragszahlung aus irgendeinem Grund fehlschlägt und beim nächsten Mal erfolgreich ist. In diesem Fall haben wir zwei Transaktionen für diesen Auftrag erstellt. Ob wir diese fehlgeschlagenen Transaktionen anzeigen möchten oder nicht, ist eine Geschäftsentscheidung, aber es ist immer eine gute Idee, wertvolle Daten zu erfassen.

Gibt es noch andere Beziehungen? Nun, viel mehr Beziehungen sind möglich, aber sie sind nicht praktisch. Zum Beispiel können wir sagen, dass ein Benutzer viele Transaktionen hat, daher sollte eine Beziehung zwischen ihnen bestehen. Hier ist zu erkennen, dass es bereits eine indirekte Beziehung gibt: Benutzer -> Bestellungen -> Transaktionen, und im Allgemeinen ist dies gut genug, da RDBMS Bestien beim Verbinden von Tabellen sind. Zweitens würde das Erstellen dieser Beziehung das Hinzufügen von a bedeuten user_id Spalte zum transactions Tabelle. Wenn wir dies für jede mögliche direkte Beziehung tun würden, würden wir die Datenbank viel mehr belasten (in Form von mehr Speicher, insbesondere wenn UUIDs verwendet werden und Indizes verwalten), wodurch das Gesamtsystem verkettet würde. Sicher, wenn das Unternehmen angibt, dass es Transaktionsdaten benötigt und diese innerhalb von 1.5 Sekunden benötigt, können wir diese Beziehung hinzufügen und die Dinge beschleunigen (Kompromisse, Kompromisse ...).

Und jetzt, meine Damen und Herren, ist es an der Zeit, den eigentlichen Code zu schreiben!

Modellbeziehungen in Laravel Eloquent verstehen (11)

Laravel model relationships — real example with code

In der nächsten Phase dieses Artikels geht es darum, uns die Hände schmutzig zu machen - aber auf nützliche Weise. Wir werden dieselben Datenbankentitäten wie im vorherigen E-Commerce-Beispiel verwenden und sehen, wie Modelle in Laravel erstellt und verbunden werden, direkt nach der Installation von Laravel!

Ich gehe natürlich davon aus, dass Sie Ihre Entwicklungsumgebung eingerichtet haben und wissen, wie Sie Composer zum Verwalten von Abhängigkeiten installieren und verwenden.

$ composer global require laravel/installer -W$ laravel new model-relationships-study

Diese beiden Konsolenbefehle installieren das Laravel-Installationsprogramm (das -W Teil wird für das Upgrade verwendet, da ich bereits eine ältere Version installiert hatte). Und falls Sie zum Zeitpunkt des Schreibens neugierig sind, ist die installierte Laravel-Version 8.5.9. Sollten Sie auch in Panik geraten und ein Upgrade durchführen? Ich würde davon abraten, da ich im Rahmen unserer Bewerbung keine wesentlichen Änderungen zwischen Laravel 5 und Laravel 8 erwarte. Einige Dinge haben sich geändert und wirken sich auf diesen Artikel aus (z. B. Model Factories), aber ich denke, Sie können den Code portieren.

Da wir das Datenmodell und seine Beziehungen bereits durchdacht haben, ist der Teil der Erstellung der Modelle trivial. Und Sie werden auch sehen (ich höre mich jetzt wie ein gebrochener Rekord an!), Wie es das Datenbankschema widerspiegelt, da es zu 100% davon abhängig ist!

Mit anderen Worten, wir müssen zuerst die Migrationen (und Modelldateien) für alle Modelle erstellen, die auf die Datenbank angewendet werden. Später können wir an den Modellen arbeiten und die Beziehungen angehen.

Mit welchem ​​Modell beginnen wir also? Das einfachste und das am wenigsten verbundene natürlich. In unserem Fall bedeutet dies die User Modell. Da Laravel mit diesem Modell geliefert wird (und ohne dieses Modell nicht funktionieren kann 🤣), ändern wir die Migrationsdatei und bereinigen das Modell entsprechend unseren einfachen Anforderungen.

Hier ist die Migrationsklasse:

class CreateUsersTable extends Migration{ public function up() { Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); }); }}

Da wir kein Projekt erstellen, müssen wir uns nicht mit Passwörtern, is_active und all dem befassen. Unser users Die Tabelle enthält nur zwei Spalten: die ID und den Namen des Benutzers.

Lassen Sie uns die Migration für erstellen Category Nächster. Da Laravel es uns ermöglicht, das Modell auch in einem einzigen Befehl zu generieren, werden wir dies nutzen, obwohl wir die Modelldatei vorerst nicht berühren werden.

$ php artisan make:model Category -mModel created successfully.Created Migration: 2021_01_26_093326_create_categories_table

Und hier ist die Migrationsklasse:

class CreateCategoriesTable extends Migration{ public function up() { Schema::create('categories', function (Blueprint $table) { $table->id(); $table->string('name'); }); }}

Wenn Sie über das Fehlen der überrascht sind down() Funktion, sei nicht; In der Praxis wird es selten zum Löschen einer Spalte oder Tabelle oder zum Ändern eines Spaltentyps verwendet, was zu Datenverlust führt, der nicht wiederhergestellt werden kann. In der Entwicklung wird die gesamte Datenbank gelöscht und die Migrationen erneut ausgeführt. Aber wir schweifen ab, also gehen wir zurück und packen die nächste Entität an. Da Unterkategorien in direktem Zusammenhang mit Kategorien stehen, halte ich es für eine gute Idee, dies als Nächstes zu tun.

(Video) Laravel Tutorial - Teil 4

$ php artisan make:model SubCategory -mModel created successfully.Created Migration: 2021_01_26_140845_create_sub_categories_table

Also gut, jetzt füllen wir die Migrationsdatei aus:

class CreateSubCategoriesTable extends Migration{ public function up() { Schema::create('sub_categories', function (Blueprint $table) { $table->id(); $table->string('name'); $table->unsignedBigInteger('category_id'); $table->foreign('category_id') ->references('id') ->on('categories') ->onDelete('cascade'); }); }}

Wie Sie sehen können, fügen wir hier eine separate Spalte mit dem Namen hinzu category_id, in dem IDs aus dem gespeichert werden categories Tabelle. Keine Preise für Vermutungen, dies schafft eine zu viele Beziehungen auf Datenbankebene.

Jetzt sind die Gegenstände an der Reihe:

$ php artisan make:model Item -mModel created successfully.Created Migration: 2021_01_26_141421_create_items_table

Und die Migration:

class CreateItemsTable extends Migration{ public function up() { Schema::create('items', function (Blueprint $table) { $table->id(); $table->string('name'); $table->text('description'); $table->string('type'); $table->unsignedInteger('price'); $table->unsignedInteger('quantity_in_stock'); $table->unsignedBigInteger('sub_category_id'); $table->foreign('sub_category_id') ->references('id') ->on('sub_categories') ->onDelete('cascade'); }); }}

Wenn Sie der Meinung sind, dass die Dinge anders gemacht werden sollten, ist das in Ordnung. Zwei Personen werden selten genau das gleiche Schema und die gleiche Architektur entwickeln. Beachten Sie eine Sache, die eine Art Best Practice ist: Ich habe den Preis als Ganzzahl gespeichert.

Warum?

Nun, die Leute erkannten, dass der Umgang mit Float-Divisionen und alles auf der Datenbankseite hässlich und fehleranfällig war, und begannen, den Preis in Bezug auf die kleinste Währungseinheit zu speichern. Wenn wir beispielsweise in USD operieren würden, würde das Preisfeld hier Cent darstellen. Im gesamten System werden die Werte und Berechnungen in Cent angegeben. Nur wenn es Zeit ist, dem Benutzer anzuzeigen oder ein PDF per E-Mail zu senden, werden wir durch 100 teilen und abrunden. Clever, was?

Modellbeziehungen in Laravel Eloquent verstehen (12)

Beachten Sie jedoch, dass ein Element in einer Viele-zu-Eins-Beziehung mit einer Unterkategorie verknüpft ist. Es ist auch mit einer Kategorie verknüpft. . . indirekt über seine Unterkategorie. Wir werden solide Demonstrationen all dieser Gymnastik sehen, aber im Moment müssen wir die Konzepte schätzen und sicherstellen, dass wir 100% klar sind.

Als nächstes ist die Order Modell und seine Migration:

$ php artisan make:model Order -mModel created successfully.Created Migration: 2021_01_26_144157_create_orders_table

Der Kürze halber werde ich nur einige der wichtigen Felder in die Migration einbeziehen. Damit meine ich, dass die Details eines Auftrags sehr viele Dinge enthalten können, aber wir werden sie auf einige beschränken, damit wir uns auf das Konzept der Modellbeziehungen konzentrieren können.

class CreateOrdersTable extends Migration{ public function up() { Schema::create('orders', function (Blueprint $table) { $table->id(); $table->string('status'); $table->unsignedInteger('total_value'); $table->unsignedInteger('taxes'); $table->unsignedInteger('shipping_charges'); $table->unsignedBigInteger('user_id'); $table->foreign('user_id') ->references('id') ->on('users') ->onDelete('cascade'); }); }}

Sieht gut aus, aber warte eine Minute! Wo sind die Artikel in dieser Reihenfolge? Wie bereits erwähnt, besteht zwischen Bestellungen und Artikeln eine Beziehung von vielen zu vielen, sodass ein einfacher Fremdschlüssel nicht funktioniert. Die Lösung ist eine sogenannte Verbindungstabelle oder Zwischentabelle. Mit anderen Worten, wir benötigen eine Verknüpfungstabelle, um die Viele-zu-Viele-Zuordnung zwischen Bestellungen und Artikeln zu speichern. In der Laravel-Welt gibt es eine integrierte Konvention, die wir befolgen, um Zeit zu sparen: Wenn ich eine neue Tabelle mit der Singularform der beiden Tabellennamen erstelle, platzieren Sie sie in Wörterbuchreihenfolge und verbinden Sie sie mit einem Unterstrich. Laravel erkennt es automatisch als Verbindungstabelle.

In unserem Fall wird die Verbindungstabelle aufgerufen item_order (Das Wort "Artikel" steht in einem Wörterbuch vor "Bestellung"). Wie bereits erläutert, enthält diese Verknüpfungstabelle normalerweise nur zwei Spalten, Fremdschlüssel für jede Tabelle.

Wir könnten hier ein Modell + eine Migration erstellen, aber das Modell wird niemals verwendet, da es eher eine Metasache ist. Daher erstellen wir eine neue Migration in Laravel und sagen, was was ist.

$ php artisan make:migration create_item_order_table --create="item_order"Created Migration: 2021_01_27_093127_create_item_order_table

Dies führt zu einer neuen Migration, die wir wie folgt ändern werden:

class CreateItemOrderTable extends Migration{ public function up() { Schema::create('item_order', function (Blueprint $table) { $table->unsignedBigInteger('order_id'); $table->foreign('order_id') ->references('id') ->on('orders') ->onDelete('cascade'); $table->unsignedBigInteger('item_id'); $table->foreign('item_id') ->references('id') ->on('items') ->onDelete('cascade'); }); }}

Wie Sie tatsächlich über eloquente Methodenaufrufe auf diese Beziehungen zugreifen können, ist ein Thema für später. Beachten Sie jedoch, dass wir diese Fremdschlüssel zunächst sorgfältig von Hand erstellen müssen. Ohne diese gibt es kein Eloquent und kein „kluges“ in Laravel. 🙂

Modellbeziehungen in Laravel Eloquent verstehen (13)

Sind wir schon da? Naja fast . . .

Wir müssen uns nur noch um ein paar Modelle kümmern. Die erste ist die Rechnungstabelle, und Sie werden sich daran erinnern, dass wir beschlossen haben, eine Eins-zu-Eins-Beziehung zu Bestellungen herzustellen.

$ php artisan make:model Invoice -mModel created successfully.Created Migration: 2021_01_27_101116_create_invoices_table

In den ersten Abschnitten dieses Artikels haben wir gesehen, dass eine Möglichkeit, eine Eins-zu-Eins-Beziehung zu erzwingen, darin besteht, den Primärschlüssel in der untergeordneten Tabelle auch zum Fremdschlüssel zu machen. In der Praxis geht kaum jemand so vorsichtig vor, und die Leute entwerfen das Schema im Allgemeinen so, wie sie es für eine Eins-zu-Viele-Beziehung tun würden. Meiner Meinung nach ist ein mittlerer Ansatz besser; Machen Sie einfach den Fremdschlüssel eindeutig und Sie haben sichergestellt, dass die IDs des übergeordneten Modells nicht wiederholt werden können:

class CreateInvoicesTable extends Migration{ public function up() { Schema::create('invoices', function (Blueprint $table) { $table->id(); $table->timestamp('raised_at')->nullable(); $table->string('status'); $table->unsignedInteger('totalAmount'); $table->unsignedBigInteger('order_id')->unique(); $table->foreign('order_id') ->references('id') ->on('orders') ->onDelete('cascade') ->unique(); }); }}

Und ja, zum x-ten Mal ist mir bewusst, dass in dieser Rechnungstabelle einiges fehlt; Unser Fokus liegt hier jedoch darauf, zu sehen, wie Modellbeziehungen funktionieren und nicht, um eine ganze Datenbank zu entwerfen.

Okay, wir haben den Punkt erreicht, an dem wir die endgültige Migration unseres Systems erstellen müssen (ich hoffe!). Der Fokus liegt nun auf dem Transaction Modell, das wir zuvor entschieden haben, ist mit dem verknüpft Order Modell. Übrigens, hier ist eine Übung für Sie: Sollte die Transaction Modell stattdessen mit dem verknüpft werden Invoice Modell? Warum und warum nicht? 🙂

$ php artisan make:model Transaction -mModel created successfully.Created Migration: 2021_01_31_145806_create_transactions_table

Und die Migration:

class CreateTransactionsTable extends Migration{ public function up() { Schema::create('transactions', function (Blueprint $table) { $table->id(); $table->timestamp('executed_at'); $table->string('status'); $table->string('payment_mode'); $table->string('transaction_reference')->nullable(); $table->unsignedBigInteger('order_id'); $table->foreign('order_id') ->references('id') ->on('orders') ->onDelete('cascade'); }); }}

Puh! Das war harte Arbeit. . . Lassen Sie uns die Migrationen ausführen und sehen, wie es uns in den Augen der Datenbank geht.

$ php artisan migrate:freshDropped all tables successfully.Migration table created successfully.Migrating: 2014_10_12_000000_create_users_tableMigrated: 2014_10_12_000000_create_users_table (3.45ms)Migrating: 2021_01_26_093326_create_categories_tableMigrated: 2021_01_26_093326_create_categories_table (2.67ms)Migrating: 2021_01_26_140845_create_sub_categories_tableMigrated: 2021_01_26_140845_create_sub_categories_table (3.83ms)Migrating: 2021_01_26_141421_create_items_tableMigrated: 2021_01_26_141421_create_items_table (6.09ms)Migrating: 2021_01_26_144157_create_orders_tableMigrated: 2021_01_26_144157_create_orders_table (4.60ms)Migrating: 2021_01_27_093127_create_item_order_tableMigrated: 2021_01_27_093127_create_item_order_table (3.05ms)Migrating: 2021_01_27_101116_create_invoices_tableMigrated: 2021_01_27_101116_create_invoices_table (3.95ms)Migrating: 2021_01_31_145806_create_transactions_tableMigrated: 2021_01_31_145806_create_transactions_table (3.54ms)

Lob sei dem Herrn! 🙏🏻🙏🏻 Sieht so aus, als hätten wir den Moment der Prüfung überlebt.

Damit sind wir bereit, Modellbeziehungen zu definieren! Dazu müssen wir zu der zuvor erstellten Liste zurückkehren und die Art der direkten Beziehungen zwischen Modellen (Tabellen) skizzieren.

Zunächst haben wir festgestellt, dass zwischen Benutzern und Bestellungen eine Eins-zu-Viele-Beziehung besteht. Wir können dies bestätigen, indem wir in die Migrationsdatei der Bestellungen gehen und das Vorhandensein des Feldes sehen user_id Dort. Dieses Feld erstellt die Beziehung, da jede Beziehung, die wir herstellen möchten, zuerst von der Datenbank berücksichtigt werden muss. Der Rest (eloquente Syntax und wo welche Funktion zu schreiben ist) ist reine Formalität.

Mit anderen Worten, die Beziehung ist bereits da. Wir müssen Eloquent nur anweisen, es zur Laufzeit verfügbar zu machen. Beginnen wir mit dem Order Modell, wo wir erklären, dass es zum gehört User Modell:

<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model;class Order extends Model{ use HasFactory; public function user() { return $this->belongsTo(User::class); }}

Die Syntax muss Ihnen vertraut sein. Wir deklarieren eine Funktion mit dem Namen user()Dies dient dazu, auf den Benutzer zuzugreifen, dem diese Bestellung gehört (der Funktionsname kann beliebig sein; es kommt darauf an, was er zurückgibt). Denken Sie noch einmal einen Moment zurück - wenn es keine Datenbank und keine Fremdschlüssel gab, eine Aussage wie $this->belongsTo wäre bedeutungslos. Es ist nur, weil es einen Fremdschlüssel auf dem gibt orders Tabelle, die Laravel verwenden kann user_id um den Benutzer mit dem gleichen nachzuschlagen id und gib es zurück. Ohne die Zusammenarbeit der Datenbank kann Laravel keine Beziehungen aus dem Nichts herstellen.

Jetzt wäre es auch schön, schreiben zu können $user->orders um auf die Bestellungen eines Benutzers zuzugreifen. Das heißt, wir müssen zum gehen User Modellieren und schreiben Sie eine Funktion für den „vielen“ Teil dieser Eins-zu-Viele-Beziehung:

(Video) Laravel Filament Admin Panel: [2] Laravel-Berechtigung von Space

<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model;class User extends Model{ use HasFactory; public $timestamps = false; public function orders() { return $this->hasMany(Order::class); }}

Ja, ich habe die Standardeinstellung stark geändert User Modell, da wir für dieses Tutorial nicht alle anderen Funktionen benötigen. Wie auch immer, die User Klasse hat jetzt eine Methode namens orders()Dies besagt, dass ein Benutzer mehreren Bestellungen zugeordnet werden kann. In der ORM-Welt sagen wir, dass die orders() Beziehung ist hier die Umkehrung der user() Beziehung hatten wir auf der Order Modell.

Aber warte eine Minute! Wie funktioniert diese Beziehung? Ich meine, es gibt nichts auf Datenbankebene, bei dem mehrere Verbindungen von der ausgehen users Tisch zum orders Tabelle.

Modellbeziehungen in Laravel Eloquent verstehen (14)

Eigentlich dais eine bestehende Verbindung, und es stellt sich heraus, es ist genug für sich allein - die Fremdschlüsselreferenz in der gespeichert orders Tabelle! Dies ist, wenn wir so etwas sagen $user->ordersLaravel trifft die orders() Funktion und weiß durch Betrachten, dass es einen Fremdschlüssel auf dem gibt orders Tabelle. Dann macht es irgendwie ein SELECT * FROM orders WHERE user_id = 23 und gibt die Abfrageergebnisse als Sammlung zurück. Natürlich besteht der Sinn eines ORM darin, SQL zu vergessen, aber wir sollten nicht vollständig vergessen, dass die zugrunde liegende Basis das RDBMS ist, das SQL-Abfragen ausführt.

Lassen Sie uns als Nächstes die Bestell- und Rechnungsmodelle durchgehen, in denen wir eine Eins-zu-Eins-Beziehung haben:

<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model;class Order extends Model{ use HasFactory; public $timestamps = false; public function user() { return $this->belongsTo(User::class); } public function invoice() { return $this->hasOne(Invoice::class); }}

Und das Rechnungsmodell:

<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model;class Invoice extends Model{ use HasFactory; public $timestamps = false; public function order() { return $this->belongsTo(Order::class); }}

Beachten Sie, dass es sich sowohl auf Datenbankebene als auch fast auf eloquenter Ebene um eine typische Eins-zu-Viele-Beziehung handelt. Wir haben gerade einige Überprüfungen hinzugefügt, um sicherzustellen, dass es eins zu eins bleibt.

Wir kommen jetzt zu einer anderen Art von Beziehung - dem Viele-zu-Viele zwischen Bestellungen und Artikeln. Denken Sie daran, dass wir bereits eine Zwischentabelle mit dem Namen erstellt haben item_order das speichert die Zuordnung zwischen den Primärschlüsseln. Wenn so viel richtig gemacht wurde, ist es trivial, die Beziehung zu definieren und damit zu arbeiten. Gemäß den Laravel-Dokumenten müssen Ihre Methoden a zurückgeben, um eine Viele-zu-Viele-Beziehung zu definieren belongsToMany() Beispiel.

Also, in der Item Modell:

<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model;class Item extends Model{ use HasFactory; public $timestamps = false; public function orders() { return $this->belongsToMany(Order::class); }}

Überraschenderweise ist die umgekehrte Beziehung fast identisch:

class Order extends Model{ /* ... other code */ public function items() { return $this->belongsToMany(Item::class); }}

Und das ist es! Solange wir die Namenskonventionen korrekt befolgt haben, kann Laravel die Zuordnungen sowie deren Position ableiten.

Da alle drei grundlegenden Arten von Beziehungen behandelt wurden (Eins-zu-Eins, Eins-zu-Viele, Viele-zu-Viele), werde ich aufhören, die Methoden für andere Modelle aufzuschreiben, da sie entlang der folgen werden gleiche Zeilen. Erstellen wir stattdessen die Fabriken für diese Modelle, erstellen Sie einige Dummy-Daten und sehen Sie diese Beziehungen in Aktion!

Wie machen wir das? Nehmen wir den schnellen und schmutzigen Pfad und werfen alles in die Standard-Seeder-Datei. Wenn wir dann die Migrationen ausführen, führen wir auch die Sämaschine aus. Also, hier ist was meine DatabaseSeeder.php Datei sieht aus wie:

<?phpnamespace Database\Seeders;use Illuminate\Database\Seeder;use App\Models\Category;use App\Models\SubCategory;use App\Models\Item;use App\Models\Order;use App\Models\Invoice;use App\Models\User;use Faker;class DatabaseSeeder extends Seeder{ public function run() { $faker = Faker\Factory::create(); // Let's make two users $user1 = User::create(['name' => $faker->name]); $user2 = User::create(['name' => $faker->name]); // Create two categories, each having two subcategories $category1 = Category::create(['name' => $faker->word]); $category2 = Category::create(['name' => $faker->word]); $subCategory1 = SubCategory::create(['name' => $faker->word, 'category_id' => $category1->id]); $subCategory2 = SubCategory::create(['name' => $faker->word, 'category_id' => $category1->id]); $subCategory3 = SubCategory::create(['name' => $faker->word, 'category_id' => $category2->id]); $subCategory4 = SubCategory::create(['name' => $faker->word, 'category_id' => $category2->id]); // After categories, well, we have items // Let's create two items each for sub-category 2 and 4 $item1 = Item::create([ 'sub_category_id' => 2, 'name' => $faker->name, 'description' => $faker->text, 'type' => $faker->word, 'price' => $faker->randomNumber(2), 'quantity_in_stock' => $faker->randomNumber(2), ]); $item2 = Item::create([ 'sub_category_id' => 2, 'name' => $faker->name, 'description' => $faker->text, 'type' => $faker->word, 'price' => $faker->randomNumber(3), 'quantity_in_stock' => $faker->randomNumber(2), ]); $item3 = Item::create([ 'sub_category_id' => 4, 'name' => $faker->name, 'description' => $faker->text, 'type' => $faker->word, 'price' => $faker->randomNumber(4), 'quantity_in_stock' => $faker->randomNumber(2), ]); $item4 = Item::create([ 'sub_category_id' => 4, 'name' => $faker->name, 'description' => $faker->text, 'type' => $faker->word, 'price' => $faker->randomNumber(1), 'quantity_in_stock' => $faker->randomNumber(3), ]); // Now that we have users and items, let's make user1 place a couple of orders $order1 = Order::create([ 'status' => 'confirmed', 'total_value' => $faker->randomNumber(3), 'taxes' => $faker->randomNumber(1), 'shipping_charges' => $faker->randomNumber(2), 'user_id' => $user1->id ]); $order2 = Order::create([ 'status' => 'waiting', 'total_value' => $faker->randomNumber(3), 'taxes' => $faker->randomNumber(1), 'shipping_charges' => $faker->randomNumber(2), 'user_id' => $user1->id ]); // now, assigning items to orders $order1->items()->attach($item1); $order1->items()->attach($item2); $order1->items()->attach($item3); $order2->items()->attach($item1); $order2->items()->attach($item4); // and finally, create invoices $invoice1 = Invoice::create([ 'raised_at' => $faker->dateTimeThisMonth(), 'status' => 'settled', 'totalAmount' => $faker->randomNumber(3), 'order_id' => $order1->id, ]); }}

Und jetzt richten wir die Datenbank erneut ein und setzen sie:

$ php artisan migrate:fresh --seedDropped all tables successfully.Migration table created successfully.Migrating: 2014_10_12_000000_create_users_tableMigrated: 2014_10_12_000000_create_users_table (43.81ms)Migrating: 2021_01_26_093326_create_categories_tableMigrated: 2021_01_26_093326_create_categories_table (2.20ms)Migrating: 2021_01_26_140845_create_sub_categories_tableMigrated: 2021_01_26_140845_create_sub_categories_table (4.56ms)Migrating: 2021_01_26_141421_create_items_tableMigrated: 2021_01_26_141421_create_items_table (5.79ms)Migrating: 2021_01_26_144157_create_orders_tableMigrated: 2021_01_26_144157_create_orders_table (6.40ms)Migrating: 2021_01_27_093127_create_item_order_tableMigrated: 2021_01_27_093127_create_item_order_table (4.66ms)Migrating: 2021_01_27_101116_create_invoices_tableMigrated: 2021_01_27_101116_create_invoices_table (6.70ms)Migrating: 2021_01_31_145806_create_transactions_tableMigrated: 2021_01_31_145806_create_transactions_table (6.09ms)Database seeding completed successfully.

Gut! Jetzt ist der letzte Teil dieses Artikels, in dem wir einfach auf diese Beziehungen zugreifen und alles bestätigen, was wir bisher gelernt haben. Sie werden erfreut sein zu wissen (ich hoffe), dass dies ein leichter und unterhaltsamer Abschnitt sein wird.

Modellbeziehungen in Laravel Eloquent verstehen (15)

Und jetzt starten wir die unterhaltsamste Laravel-Komponente - die interaktive Tinker-Konsole!

$ php artisan tinkerPsy Shell v0.10.6 (PHP 8.0.0 — cli) by Justin Hileman>>>

Accessing one-to-one model relationships in Laravel Eloquent

Okay, lassen Sie uns zunächst auf die Eins-zu-Eins-Beziehung zugreifen, die wir in unseren Bestell- und Rechnungsmodellen haben:

>>> $order = Order::find(1);[!] Aliasing 'Order' to 'App\Models\Order' for this Tinker session.=> App\Models\Order {#4108 id: 1, status: "confirmed", total_value: 320, taxes: 5, shipping_charges: 12, user_id: 1, }>>> $order->invoice=> App\Models\Invoice {#4004 id: 1, raised_at: "2021-01-21 19:20:31", status: "settled", totalAmount: 314, order_id: 1, }

Merken Sie etwas? Denken Sie daran, dass diese Beziehung auf Datenbankebene eine Eins-zu-Viele-Beziehung ist, wenn nicht aufgrund der zusätzlichen Einschränkungen. Laravel hätte also eine Sammlung von Objekten (oder nur ein Objekt) als Ergebnis zurückgeben können, und das wäre technisch korrekt. ABER . . . Wir haben Laravel gesagt, dass es sich um eine Eins-zu-Eins-Beziehung handelt. Das Ergebnis ist also eine einzelne eloquente Instanz. Beachten Sie, wie beim Zugriff auf die umgekehrte Beziehung dasselbe passiert:

$invoice = Invoice::find(1);[!] Aliasing 'Invoice' to 'App\Models\Invoice' for this Tinker session.=> App\Models\Invoice {#3319 id: 1, raised_at: "2021-01-21 19:20:31", status: "settled", totalAmount: 314, order_id: 1, }>>> $invoice->order=> App\Models\Order {#4042 id: 1, status: "confirmed", total_value: 320, taxes: 5, shipping_charges: 12, user_id: 1, }

Accessing one-to-many model relationships in Laravel Eloquent

Wir haben eine Eins-zu-Viele-Beziehung zwischen Benutzern und Bestellungen. Lassen Sie uns jetzt daran „basteln“ und die Ausgabe sehen:

>>> User::find(1)->orders;[!] Aliasing 'User' to 'App\Models\User' for this Tinker session.=> Illuminate\Database\Eloquent\Collection {#4291 all: [ App\Models\Order {#4284 id: 1, status: "confirmed", total_value: 320, taxes: 5, shipping_charges: 12, user_id: 1, }, App\Models\Order {#4280 id: 2, status: "waiting", total_value: 713, taxes: 4, shipping_charges: 80, user_id: 1, }, ], }>>> Order::find(1)->user=> App\Models\User {#4281 id: 1, name: "Dallas Kshlerin", }

Genau wie erwartet führt der Zugriff auf die Bestellungen eines Benutzers zu einer Sammlung von Datensätzen, während die Umkehrung nur einen einzigen erzeugt User Objekt. Mit anderen Worten, eins zu viele.

Accessing many-to-many model relationships in Laravel Eloquent

Lassen Sie uns nun eine Beziehung untersuchen, die viele zu viele ist. Wir haben eine solche Beziehung zwischen Artikeln und Bestellungen:

>>> $item1 = Item::find(1);[!] Aliasing 'Item' to 'App\Models\Item' for this Tinker session.=> App\Models\Item {#4253 id: 1, name: "Russ Kutch", description: "Deserunt voluptatibus omnis ut cupiditate doloremque. Perspiciatis officiis odio et accusantium alias aut. Voluptatum provident aut ut et.", type: "adipisci", price: 26, quantity_in_stock: 65, sub_category_id: 2, }>>> $order1 = Order::find(1);=> App\Models\Order {#4198 id: 1, status: "confirmed", total_value: 320, taxes: 5, shipping_charges: 12, user_id: 1, }>>> $order1->items=> Illuminate\Database\Eloquent\Collection {#4255 all: [ App\Models\Item {#3636 id: 1, name: "Russ Kutch", description: "Deserunt voluptatibus omnis ut cupiditate doloremque. Perspiciatis officiis odio et accusantium alias aut. Voluptatum provident aut ut et.", type: "adipisci", price: 26, quantity_in_stock: 65, sub_category_id: 2, pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4264 order_id: 1, item_id: 1, }, }, App\Models\Item {#3313 id: 2, name: "Mr. Green Cole", description: "Maxime beatae porro commodi fugit hic. Et excepturi natus distinctio qui sit qui. Est non non aut necessitatibus aspernatur et aspernatur et. Voluptatem possimus consequatur exercitationem et.", type: "pariatur", price: 381, quantity_in_stock: 82, sub_category_id: 2, pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4260 order_id: 1, item_id: 2, }, }, App\Models\Item {#4265 id: 3, name: "Brianne Weissnat IV", description: "Delectus ducimus quia voluptas fuga sed eos esse. Rerum repudiandae incidunt laboriosam. Ea eius omnis autem. Cum pariatur aut voluptas sint aliquam.", type: "non", price: 3843, quantity_in_stock: 26, sub_category_id: 4, pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4261 order_id: 1, item_id: 3, }, }, ], }>>> $item1->orders=> Illuminate\Database\Eloquent\Collection {#4197 all: [ App\Models\Order {#4272 id: 1, status: "confirmed", total_value: 320, taxes: 5, shipping_charges: 12, user_id: 1, pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4043 item_id: 1, order_id: 1, }, }, App\Models\Order {#4274 id: 2, status: "waiting", total_value: 713, taxes: 4, shipping_charges: 80, user_id: 1, pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4257 item_id: 1, order_id: 2, }, }, ], }

Diese Ausgabe kann etwas schwindelerregend sein, aber beachten Sie, dass Artikel1 Teil der Artikel von order1 ist und umgekehrt. So richten wir die Dinge ein. Schauen wir uns auch die Zwischentabelle an, in der die Zuordnungen gespeichert sind:

>>> use DB;>>> DB::table('item_order')->select('*')->get();=> Illuminate\Support\Collection {#4290 all: [ {#4270 +"order_id": 1, +"item_id": 1, }, {#4276 +"order_id": 1, +"item_id": 2, }, {#4268 +"order_id": 1, +"item_id": 3, }, {#4254 +"order_id": 2, +"item_id": 1, }, {#4267 +"order_id": 2, +"item_id": 4, }, ], }

Conclusion

Ja, das ist es wirklich! Es war ein sehr langer Artikel, aber ich hoffe, er war nützlich. Ist das alles, was man über Laravel-Modelle wissen muss?

Traurigerweise Nein. Das Kaninchenloch ist wirklich sehr, sehr tief und es gibt viele weitere herausfordernde Konzepte wie Polymorphic Relationships und Leistungsoptimierungund so weiter, auf die Sie stoßen werden, wenn Sie als Laravel-Entwickler wachsen. Derzeit reicht das, was dieser Artikel behandelt, ungefähr 70% der Entwickler in 70% der Fälle aus. Es wird sehr lange dauern, bis Sie das Bedürfnis verspüren, Ihr Wissen zu verbessern.

Mit dieser Einschränkung möchte ich, dass Sie diese wichtigste Erkenntnis wegnehmen: Nichts ist dunkle Magie oder unerreichbar Programmierung. Es ist nur so, dass wir die Grundlagen und den Aufbau der Dinge nicht verstehen, was uns kämpfen lässt und uns frustriert fühlt.

Damit . . . ?

Investiere in dich selbst! Kurse, Bücher, Artikel, andere Programmiergemeinschaften (Python ist meine Empfehlung Nr. 1) - Verwenden Sie alle Ressourcen, die Sie finden können, und verbrauchen Sie sie regelmäßig, wenn auch langsam. Ziemlich bald wird sich die Anzahl der Fälle, in denen Sie wahrscheinlich das Ganze verpfuschen werden, drastisch verringern.

Okay, genug zu predigen. Einen schönen Tag noch! 🙂

(Video) Introduction to Laravel Magellan - Our new PostGIS Package - clickbar. fullstack talk

Videos

1. Episode 6 – Deep Dive Laravel
(PHPDevRadio)
2. Laravel 8: Multi-Auth/ Admin Panel From Scratch w/ Simple Roles - Ep.#11 Gates & Policies
(Designated Coder)
3. Laravel E-Commerce: [37] Filament-Repeater-Feld
(Designated Coder)
4. Laravel E-Commerce: [29] Benutzer-Dashboard & Profil
(Designated Coder)
5. Laravel 5.5 Tutorials | Routes in Laravel | Web.php file #6
(Bitfumes)
6. Strategisches Domain-driven Design - Grundlegende Patterns unter der Lupe
(Eberhard Wolff)
Top Articles
Latest Posts
Article information

Author: Kelle Weber

Last Updated: 02/11/2023

Views: 5790

Rating: 4.2 / 5 (53 voted)

Reviews: 92% of readers found this page helpful

Author information

Name: Kelle Weber

Birthday: 2000-08-05

Address: 6796 Juan Square, Markfort, MN 58988

Phone: +8215934114615

Job: Hospitality Director

Hobby: tabletop games, Foreign language learning, Leather crafting, Horseback riding, Swimming, Knapping, Handball

Introduction: My name is Kelle Weber, I am a magnificent, enchanting, fair, joyous, light, determined, joyous person who loves writing and wants to share my knowledge and understanding with you.