Help us understand the problem. What is going on with this article?

Laravel 5.7 + GraphQL(Relation編)

LaravelとGraphQLでAPI開発こちらの記事の続きです。

今回はGraphQLでリレーションのデータを取得する方法をご紹介します。

シリーズ記事

記事のモデル、マイグレーション、ファクトリを作る

https://github.com/ucan-lab/practice-laravel-graphql/commit/1c17b14bd679833ccc889cd58504f49cbd2df9f0

$ php artisan make:model -mf Post

GraphQLを使うのでコントローラは作りません。
ユーザーのモデルとシーダーに記事リレーションを修正します。

$ php artisan migrate:fresh --seed

マイグレーション&シーディングを実行する。
これは本題ではないのでコミットを参照ください。

1対多のリレーションデータを取得の例

https://github.com/ucan-lab/practice-laravel-graphql/commit/64d8c2fa7b8f6bfe96fd46b7d14848c06ee0a00b

PostTypeのGraphQL独自型の定義

$ php artisan make:graphql:type PostType

config/graphql.php

    'types' => [
        App\GraphQL\Type\UserType::class,
        App\GraphQL\Type\PostType::class,
        // custom scalar type
        App\GraphQL\Scalars\DateTimeType::class,
    ],

PostType を登録します。

app/GraphQL/Type/PostType.php

<?php

declare(strict_types = 1);

namespace App\GraphQL\Type;

use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Type as BaseType;
use GraphQL;

class PostType extends BaseType
{
    protected $attributes = [
        'name' => 'PostType',
        'description' => 'post type'
    ];

    public function fields() : array
    {
        return [
            'id' => [
                'type' => Type::id(),
                'description' => 'The id of the user'
            ],
            'title' => [
                'type' => Type::string(),
                'description' => 'The title of post',
            ],
            'content' => [
                'type' => Type::string(),
                'description' => 'The content of post',
            ],
        ];
    }
}

PostType GraphQL独自型のfieldsを定義します。

app/GraphQL/Type/UserType.php

    public function fields() : array
    {
        return [
            'posts' => [
                'type' => Type::listOf(GraphQL::type('PostType')),
                'description' => 'The posts of user',
            ],
        ];
    }

1対多 動作確認

{
  user(id: 1) {
    id
    name
    posts {
      title
      content
    }
  }
}

posts { ... } と書いてあげるだけでリレーションデータを引っ張ってきてくれます!

{
  "data": {
    "user": {
      "id": "1",
      "name": "Prof. Mozell Beer",
      "posts": [
        {
          "title": "Nihil in autem autem molestiae.",
          "content": "Quod dolores sunt aspernatur voluptatem officia aut voluptatum. In dolores non dolore ut nesciunt voluptatem laboriosam. Pariatur aut et tenetur dolor doloribus."
        },
        {
          "title": "Dolores tenetur deserunt velit qui et in minus velit.",
          "content": "Quaerat sint excepturi dicta ut maiores. Est corporis expedita aut rerum sapiente. Explicabo hic dolorem nulla animi delectus voluptatem."
        },
        {
          "title": "Quia nostrum sapiente accusamus qui saepe.",
          "content": "Debitis praesentium autem est doloribus eius saepe. Iste dolorum consectetur incidunt ea aliquid et voluptas aut. Dignissimos sed autem eius adipisci. Eligendi eius pariatur aut earum."
        },
        {
          "title": "Quaerat corrupti inventore consectetur ipsam blanditiis.",
          "content": "Ad facere non officia commodi earum. Officiis deleniti itaque occaecati qui natus et. Fuga molestias alias atque adipisci. Itaque id praesentium ea."
        },
        {
          "title": "Nihil a illum magnam.",
          "content": "A quis deleniti quia quasi odio. Quas qui odit placeat sit tempora nulla voluptas. Consequatur nemo sit consequatur enim ratione."
        },
        {
          "title": "Aut tempore aut et enim.",
          "content": "Provident qui velit magni et. Molestiae qui dignissimos assumenda voluptas excepturi magnam ut. Nesciunt odit atque repudiandae ex delectus quia numquam."
        },
        {
          "title": "Beatae ipsa dignissimos eveniet officia eveniet explicabo.",
          "content": "Soluta expedita aut sit tempore. Et perferendis nemo culpa sit velit voluptatum. Quis natus iusto aut consectetur ex. Error voluptates ut quam. Ut molestias incidunt nihil rerum et itaque blanditiis."
        },
        {
          "title": "Quo non labore vel neque.",
          "content": "Officiis recusandae sunt ullam sit eos. Aspernatur architecto repellendus aut aliquid natus. Iusto praesentium perspiciatis veritatis sit ratione sequi."
        },
        {
          "title": "Dignissimos quia est fugit omnis sit dolores alias.",
          "content": "Non maiores nesciunt adipisci. Est aut distinctio soluta ducimus sed. Harum labore ut voluptas ea qui."
        },
        {
          "title": "Minus asperiores dolorem provident quo.",
          "content": "Voluptas ut odio qui eum totam sed neque. Necessitatibus excepturi eius quas iure. Quia enim voluptatem est molestiae non. Tenetur similique ullam qui iure enim voluptates voluptatem."
        }
      ]
    }
  }
}

こんな感じでリレーションデータを取得できます。
これの凄いところは、定義を追加しただけでライブラリ側で判断してユーザーが投稿した記事の情報を取得できているところです。

1対多 (Inverse)のリレーションデータを取得の例

記事のQueryを作る

$ php artisan make:graphql:query PostQuery
$ php artisan make:graphql:query PostsQuery

app/GraphQL/Type/PostType.php

    public function fields() : array
    {
        return [
            'user' => [
                'type' => GraphQL::type('UserType'),
                'description' => 'The user of post',
            ],
        ];
    }

1対多 (Inverse)の設定はこれだけです。

1対多 (Inverse) 動作確認

{
  post(id: 123) {
    id
    title
    user {
      id
      name
    }
  }
}

user { ... } と書いてあげるだけでリレーションデータを引っ張ってきてくれます!

{
  "data": {
    "post": {
      "title": "Quae itaque maxime sit eius ducimus qui quas.",
      "user": {
        "id": "13",
        "name": "Melany Johnson"
      }
    }
  }
}

とても簡潔に記述できます。

リレーションデータ取得処理のカスタマイズ

app/GraphQL/Type/PostType.php

    /**
     * ユーザー
     *
     * @param Post $root
     * @param array $args
     * @return User
     */
    protected function resolveUserField(Post $root, array $args) : User
    {
        logger('test');
        return $root->user;
    }

resolveフィールド名Field resolver関数を用意すればリレーションデータを取得する前に処理を差し込むことができます。
とても柔軟に対応できるので素敵だなぁと思いました。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away