LaravelとGraphQLでAPI開発こちらの記事の続きです。
今回はGraphQLでリレーションのデータを取得する方法をご紹介します。
シリーズ記事
- LaravelとGraphQLでAPI開発
- Laravel 5.7 + GraphQL(Install編)
- Laravel 5.7 + GraphQL(ScalarType編)
- Laravel 5.7 + GraphQL(Relation編)
- Laravel 5.7 + GraphQL(Dump Server編)
- Laravel 5.7 + GraphQL(Pagination編)
- Laravel 5.7 + GraphQL(ErrorHandling編)
- Laravel 5.7 + GraphQL(Test編)
記事のモデル、マイグレーション、ファクトリを作る
$ php artisan make:model -mf Post
GraphQLを使うのでコントローラは作りません。
ユーザーのモデルとシーダーに記事リレーションを修正します。
$ php artisan migrate:fresh --seed
マイグレーション&シーディングを実行する。
これは本題ではないのでコミットを参照ください。
1対多のリレーションデータを取得の例
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関数を用意すればリレーションデータを取得する前に処理を差し込むことができます。
とても柔軟に対応できるので素敵だなぁと思いました。