Panda Noir

JavaScript の限界を究めるブログです。

Laravel5.4 でGraphQL式のAPIを実装してみた

一応アクセスしたら結果が返ってくるようにはなりました。なんで動くのかはLaravel初心者の僕には理解できませんでした。

対象読者

LaravelもデータベースもよくわからないけどGraphQLを試してみたい人。

環境

  • CentOS 7.3.1611
  • PHP 7.1.4
  • Laravel 5.4.28
  • Laravel GraphQL 1.0.0
  • MySQL ver14.14 Distrib 5.7.18

こんな感じです。

作業

Laravel GraphQLをインストー

(Laravelやその他の必要なものはインストールが済んでいるとします) Laravelについて詳しく知りませんが、たぶんLaravel 5.4に対する設定がLaravel GraphQLに書いてあるものと若干異なると思います。

// config/app.php
    'providers' => [
        ...
        Folklore\GraphQL\ServiceProvider::class, // 追加
        ...
    ],
    'aliases' => [
        ...
        'GraphQL' => Folklore\GraphQL\Support\Facades\GraphQL::class, // 追加
        ...
    ]
$ php artisan vendor:publish --provider="Folklore\GraphQL\ServiceProvider"

これで

Laravelプロジェクトを作成

Laravel 5.1 のインストール – ララ帳

ここを参考にプロジェクトを作ります。

$ composer create-project laravel/laravel --prefer-dist graphql

config/database.phpと.envのhostやdatabaseを適当にいじります。

// config/database.php
'mysql' => [
    ...
    'database' => env('DB_DATABASE', 'test'),
    'username' => env('DB_DATABASE', 'test'),
    'password' => env('DB_DATABASE', 'test'),
]
// .env
DB_DATABASE=test
DB_USERNAME=test
DB_PASSWORD=test

ここで設定したデータベース、ユーザーはあらかじめ作成しておいてください。

テスト用にユーザーのテーブルを作る

デフォルトで用意されているユーザー用のテーブルを作ります。といってもmigrateコマンドを実行するだけです。

$ php artisan migrate

これでユーザー用のテーブルができました。

テスト用のデータを追加する

blog.asial.co.jp

ここを参考にテスト用のユーザを作成します。

// database/seeds/DatabaseSeeder.php
    public function run()
    {
        $faker = \Faker\Factory::create();
        
        $user = new \App\User();
        $user->name = $faker->name;
        $user->email = $faker->unique()->safeEmail;
        $user->password = bcrypt('password');
        $user->remember_token = str_random(10);
        $user->save();
    }
$ php artisan db:seed

これでテストデータが追加されました。

 GraphQLの設定を行う

Laravel GraphQLのドキュメントを参考にして作業します。しかし、Laravel初心者には難解だったので補足説明しつつ書きます。

まず設定を変更します。

// config/graphql.php
    'schemas' => [
        'default' => [
            'query' => [
                'users' => 'App\GraphQL\Query\UsersQuery'
            ],
            'mutation' => []
        ]
    ],
    'types' => [
        'App\GraphQL\Type\UserType'
    ]

次に必要なディレクトリを作ります。

$ mkdir app/GraphQL/Type -p
$ mkdir app/GraphQL/Query -p

必要ファイルを作成します

app/GraphQL/Type/UserType.phpを作成します。

<?php
namespace App\GraphQL\Type;

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

class UserType extends GraphQLType {

    protected $attributes = [
        'name' => 'User',
        'description' => 'A user'
    ];
  
  /*
     * Uncomment following line to make the type input object.
     * http://graphql.org/learn/schema/#input-types
     */
    // protected $inputObject = true;

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


    // If you want to resolve the field yourself, you can declare a method
    // with the following format resolve[FIELD_NAME]Field()
    protected function resolveEmailField($root, $args)
    {
        return strtolower($root->email);
    }

}

app/GraphQL/Query/UsersQuery.phpを作成します。

<?php
namespace App\GraphQL\Query;

use GraphQL;
use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Query;
use App\User;

class UsersQuery extends Query {

    protected $attributes = [
        'name' => 'users'
    ];

    public function type()
    {
        return Type::listOf(GraphQL::type('User'));
    }

    public function args()
    {
        return [
            'id' => ['name' => 'id', 'type' => Type::string()],
            'email' => ['name' => 'email', 'type' => Type::string()]
        ];
    }

    public function resolve($root, $args)
    {
        if(isset($args['id']))
        {
            return User::where('id' , $args['id'])->get();
        }
        else if(isset($args['email']))
        {
            return User::where('email', $args['email'])->get();
        }
        else
        {
            return User::all();
        }
    }

}

アクセスしてみる

以上で完成です。早速アクセスしてみましょう。

http://example.com/graphql/graphql?query={users{id,email}} これで

{"data":{"users":[{"id":"1","email":"ole70@example.net"}]}}

のようなデータが得られたら成功です(作成したユーザーデータはランダムに生成されるのでemailは異なると思います)。

終わりに

1日と少しかかりましたが、なんとか形になりました。しかし動作原理を全く理解できていないのでこれからコードをいじりつつ理解していこうと思います。

…今回の記事、もしかしてLaravel中級者には全くの不要な記事だったのでしょうか。