コンテンツにスキップ

Eloquent 入門

Lighthouseでは、Eloquentモデルに対するクエリやミューテーションを簡単に実行できます。

モデルの定義

Eloquentのモデルは通常、GraphQLの型に直接マッピングされます。

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

主キーに対応するフィールドの名前は id とすることを強くお勧めします。 Apollo のような人気のあるクライアントライブラリでは、この規約に従うことですぐにキャッシュ機能を利用できるようになります。

モデルの取得

独自のリゾルバを手動で定義する代わりに、Lighthouseにクエリを構築させることができます。

type Query {
  users: [User!]! @all
}

@allディレクティブは、モデル名を解決しようとするFieldの戻り値の型と同じと仮定して、自動でEloquentを使用してフィールドを解決するよう試みます。

以下のクエリ:

{
  users {
    id
    name
  }
}

は、下記の結果を返します。

{
  "data": {
    "users": [
      { "id": 1, "name": "James Bond" },
      { "id": 2, "name": "Madonna" }
    ]
  }
}

ページネーション

@paginate ディレクティブを利用するこどで、大きなサイズのモデルのリストをチャンク化したクエリとして取得できます。

type Query {
  posts: [Post!]! @paginate
}

上記のスキーマの定義は自動的にこのように変換されます。

type Query {
  posts(first: Int!, page: Int): PostPaginator
}

type PostPaginator {
  data: [Post!]!
  paginatorInfo: PaginatorInfo!
}

そして、以下のように問い合わせできます。

{
  posts(first: 10) {
    data {
      id
      title
    }
    paginatorInfo {
      currentPage
      lastPage
    }
  }
}

クエリに制約を追加する

Lighthouseは、クライアントに追加のクエリ機能を与えることで、クエリを強化するための組み込みディレクティブを提供します。

以下のフィールド定義では、IDで一件のユーザーをフェッチすることができます。

type Query {
  user(id: ID! @eq): User @find
}

このフィールドには、次のように問い合わせることができます:

{
  user(id: 69) {
    name
  }
}

そして、結果が見つかった場合は、次のように結果を受け取ります。

{
  "data": {
    "user": {
      "name": "Chuck Norris"
    }
  }
}

ローカルスコープ

ローカルスコープは、Eloquentのモデルで再利用可能なクエリ条件を指定するためによく使われます。

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function scopeVerified(Builder $query): Builder
    {
        return $query->whereNotNull('email_verified_at');
    }
}

モデルを問い合わせるためのディレクティブ、例えば @all@first を使用することで、これらのスコープを再利用することができます。

type Query {
  users: [User]! @all(scopes: ["verified"])
}

このクエリでは、以下のSQLが生成されます:

SELECT * FROM `users` WHERE `email_verified_at` IS NOT NULL

生成

@createディレクティブを使用することが、サーバー上にデータを作成する最も簡単な方法です。

type Mutation {
  createUser(name: String!): User! @create
}

このmutationはフィールドに渡された引数を使用して、新しいモデルのインスタンスを作成します:

This mutation will use the arguments passed to the field to create a new model instance:

mutation {
  createUser(name: "Donald") {
    id
    name
  }
}

新しく作成されたユーザが結果として返されます。:

{
  "data": {
    "createUser": {
      "id": "123",
      "name": "Donald"
    }
  }
}

更新

モデルの更新は@updateディレクティブで行えます。

type Mutation {
  updateUser(id: ID!, name: String): User @update
}

GraphQLではデータの一部だけを更新することができるので、id以外の引数はオプションにしたほうがよいでしょう。

mutation {
  updateUser(id: "123", name: "Hillary") {
    id
    name
  }
}
{
  "data": {
    "updateUser": {
      "id": "123",
      "name": "Hillary"
    }
  }
}

更新処理は該当データがない場合に失敗します。このためミューテーションは、nullを返すことがあります。

The update may fail to find the model you provided and return null:

{
  "data": {
    "updateUser": null
  }
}

アップサート

@upsert ディレクティブを使用して、指定された id を持つモデルがあれば更新し、なければ作成することができます。

type Mutation {
  upsertUser(id: ID!, name: String!, email: String): User @upsert
}

upsertはデータを作成または更新することができるので、入力パラメータでは最低限必要なフィールドだけをnon-nullにする必要があります。 idフィールドは常に必須です。

mutation {
  upsertUser(id: "123", name: "Hillary") {
    id
    name
    email
  }
}
{
  "data": {
    "upsertUser": {
      "id": "123",
      "name": "Hillary",
      "email": null
    }
  }
}

削除

モデルの削除は @delete ディレクティブを使えば簡単にできます。危険なほど簡単に行えます。

type Mutation {
  deleteUser(id: ID!): User @delete
}

単に削除したいユーザのIDを指定して削除のmutationをコールすれば良いです。

mutation {
  deleteUser(id: "123") {
    secret
  }
}

このmutationは削除されたオブジェクトを返します。ですので、削除されたデータを取得する最後の機会があります。この仕組みをうまく使ってください。

{
  "data": {
    "deleteUser": {
      "secret": "Pink is my favorite color!"
    }
  }
}