コンテンツにスキップ

ポリモーフィック・リレーションシップ

Laravelと同様に、スキーマのなかでポリモーフィック・リレーションシップを定義できます。

一対一

Laravelのサンプルドキュメントと同じように、モデルの構造を定義したとします。 PostUser という2つのモデルがあり、どちらも Image が割り当てられているとします。

まずは、リレーションシップのない単純な型定義から始めてみましょう。

type Post {
  id: ID!
  name: String!
}

type User {
  id: ID!
  name: String!
}

type Image {
  id: ID!
  url: String!
}

First, let's go ahead and add the relations to Image since they are straightforward. The field name should match your relationship method name and be annotated with the @morphOne directive.

まず、簡単な Image にリレーションの追加から初めてみましょう。 フィールド名はリレーションシップのメソッド名と一致させて、@morphOneディレクティブを使ってアノテーションする必要があります。

type Post {
  id: ID!
  name: String!
  image: Image! @morphOne
}

type User {
  id: ID!
  name: String!
  image: Image @morphOne
}

アプリケーションのルールによって、リレーションシップが必要な場合もあれば、なくてもよい場合もあります。 上記の例では、Postは常にImageを持たなければなりませんが、User必ずしも持つ必要はありません。

逆にImageが別のモデルにリンクされるかもしれないことを表現するために、[union type] (../the-basics/types.md#union) を定義する必要があります。

union Imageable = Post | User

次にこのユニオン型を Image 型のフィールドから参照します。 ここで、パフォーマンスの最適化のために @morphTo ディレクティブを使用することができます。

type Image {
  id: ID!
  url: String!
  imageable: Imageable! @morphTo
}

デフォルトの型リゾルバによって、Eloquentモデルを扱う際にどの具体オブジェクトの型が返されるかを判断することができるようになります。ですので、この定義で問題ありません。

一対多

上記の例に基づいて、アプリケーションにおいて1つのPostが複数の画像を持つことが可能なように変更できます。

フィールド imagesImage オブジェクトのリストを返すようになり、アノテーションは @morphMany ディレクティブを使用します。

type Post {
  id: ID!
  name: String!
  images: [Image]! @morphMany
}

type Image {
  id: ID!
  url: String!
  imageable: Imageable! @morphTo
}

union Imageable = Post | User