Polymorphic Relationships in Laravel

Paul Böhm

In Software Projekten kann es häufiger vorkommen, dass ein Model ein Verknüpfung zu verschiedenen Entitäten haben kann. Diese Models haben die gleiche Struktur, egal zu welcher Entität sie gehören.

Ein gutes Beispiel hierfür sind Kommentare, diese können oft zu mehreren Objekten gehören. Nehmen wir einen Webshop, in dem der Nutzer z. B. einen Artikel und eine Bestellung mit einem Kommentar versehen kann.

In diesem Artikel schauen wir uns an wie die Beziehung in Laravel funktioniert. Angefangen vom Initialisieren in der Datenbank bis zur Verwendung in der Applikation.

Was sind Polymorphic Relationships

Wir beginnen mit oben genannten Beispiel und wie dieses ohne die Polymorphic Relationships aussehen würde.

orders:
  id
  date

  user
  
order_comments:
  id
  order_id
  comment
  date
  
articles:
  id
  name
  price
  
article_comments:
  id
  articles_id
  comment
  date

In diesem Beispiel sehen wir, dass die beiden Tabellen order_comments und article_comments bis auf den Fremdschlüssel identisch sind, also in der Grundidee die gleiche Funktion erfüllen.

Mit Polymorphic Relationships, können wir dieses Konstrukt umbauen und vereinfachen. Zusätzlich bietet es uns die Möglichkeit weitere Models mit Kommentaren zu versehen.

orders:
  id
  date
  user

articles:
  id
  name
  price

comments:
  id
  commentable_id
  commentable_type
  body
  date

Was macht Polymorphic Relationships aus? Als erstes sehen wir, dass die beiden Tabellen article_comments und order_comments mit der Tabelle comments ersetzt wurden. In der comments Tabelle sind dafür jetzt die beiden Spalten commentable_id und commentable_type neu.

Die commentable_id in unserem Beispiel verhält sich ähnlich wie ein Fremdschlüssel und enthält die id des zu referenzierenden Objekts. Der entscheidende Unterschied ist der commentable_type, dieser enthält den Objekttyp. In unserem Beispiel kann dieser „order“ oder auch „article“ sein.

Doch wie sieht das ganze nun in Laravel aus?

Beginnen wir mit der Migration:

Schema::create('orders', function (Blueprint $table) {
    $table->increments('id');
    $table->date('date');
    $table->text('user');
});

Schema::create('articles', function (Blueprint $table) {
    $table->increments('id');
    $table->text('name');
    $table->number('price');
});

Schema::create('comments', function (Blueprint $table) {
    $table->increments('id');
    $table->morphs(‘commentable’);
    $table->text('body');
    $table->date('date');
});

$table→morphs('commentable') erstellt automatisch mit Hilfe des angegeben Textes in der Klammer die Spalten id and type. Daraus ergeben sich die beiden Spalten commentable_id und commentable_type.

Als nächstes definieren wir die Models:

//file: Post.php
<?php

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    // Get all of the post's comments.

    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}


//file: Page.php
<?php

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    // Get all of the page's comments.

    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

//file: Comment.php
<?php

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    // Get all of the models that own comments.

    public function commentable()
    {
        return $this->morphTo();
    }
}

Mit Hilfe der Funktionen morphMany() und morphTo() können wir die Polymorphic Relationships definieren.

Die beiden Klassen Article und Order haben jeweils die Funktion comments() mit der Methode morphMany() und dem Rückgabewert App/Comment. Mit dieser Funktion definieren wir die Relation der Kommentare zu dem zugehörigen Model.

TIPP! Mit dieser Definition kann man Kommentare für weitere Models definieren.

Die Klasse comment besitzt die Funktion commentable() mit der Methode morphTo() . Diese Funktion liefert die spezifische Klasse, die zu einem Kommentar gehört. In unserem Beispiel können das die Klassen order und article sein.

Einmal definiert können wir auf diese Funktionen zugreifen:

Kommentare für Artikel und Bestellungen:

// Bestellung
$order= Order::find(1);

  foreach($order->comment as $comment)
  {
    // working with comment here...
  }

// Artikel
$article = Article::find(2);

  foreach($Article->comment as $comment)
  {
    // working with comment here...
  }

Umgekehrt können wir uns die Klasse eines Kommentars mit der Funktion commentable holen.

$comment = Comment::find(23);
  // getting the model...
  var_dump($comment->commentable);

Haben Sie noch Fragen oder wünschen eine Beratung? Nehmen Sie gerne mit uns Kontakt auf oder besuchen Sie unsere Webseite.

Gerne können Sie hier auch andere Artikel zum Thema Laravel anschauen.