# Validation の実装

実際のアプリケーション開発では、 入力値のバリデーション処理が必要になるケースがほとんどです。

GraphQL におけるバリデーションの処理と、 エラーレスポンスの表示方法を確認しておきましょう。

# Validation の実装

先程定義した createTasks にバリデーションの実装を追加すると 以下のようなコードになります。

app/GraphQL/Mutations/CreateTasks.php を、 以下のような形で修正してみましょう。

<?php
namespace App\GraphQL\Mutations;

use App\Models\Task;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Validator;
use Nuwave\Lighthouse\Exceptions\ValidationException;

class CreateTasks
{
    public function __invoke($rootValue, array $args)
    {
        $rules = [
            "tasks" => ["required","array","max:5"],
            "tasks.*.name" => ["required","max:50"],
            "tasks.*.priority" => ["required",Rule::in(1,2,3,4,5)],
        ];
        $val = validator($args,$rules);
        assert($val instanceof Validator);
        if(!$val->passes()){
            throw new ValidationException($val);
        }

        $tasks = [];
        foreach ($args["tasks"] as $input) {
            $task = new Task();
            $task->name = "【{$input["name"]}】" ;
            $task->priority = $input["priority"];
            $task->save();
            $tasks[] = $task->refresh();
        }
        return $tasks;
    }
}

Valiation の実装では、 Laravel の validator 関数を利用するのが便利です。 validator 関数では、 第一引数に入力値の $args を 第二引数に ルールの一覧をセットし、以下のようなルールを設定しています。

  • tasks : 配列形式であること
  • tasks.*.name : 50文字以下であること
  • tasks.*.priority : 1,2,3,4,5 いずれかの数字であること

バリデーションのエラーが発生している際には、 Nuwave\Lighthouse\Exceptions\ValidationException を throw することで、 バリデーションエラーのレスポンスを返すことが出来ます。

Nuwave\Lighthouse\Exceptions\ValidationException は lighthouse 側で用意された、 バリデーションエラー専用の 例外クラスです。

TIP

通常、Laravel の バリデーションエラーでは、 Illuminate\Validation\ValidationException を throw しますが、 lighthouse では、Nuwave\Lighthouse\Exceptions\ValidationException を throw します。

# Validation エラーのレスポンス

Validation の実装を確認するために、altair で以下のような クエリを発行してみましょう。・

Query

mutation($input: [createTaskInput!]!){
  createTasks(tasks: $input){
    name
    priority
  }
}

Variables

{
  "input": [
    {
      "name": "ミーティングの資料を作る",
      "priority": 3
    },
    {
      "name": "借りた本を返す",
      "priority": 7
    }
  ]
}

上記のクエリは、 "priority": 7 がバリデーションエラーとなります。

バリデーションのエラー時には、以下のような形のレスポンスが取得できます。

{
  "errors": [
    {
      "message": "The given data was invalid.",
      "extensions": {
        "validation": {
          "tasks.1.priority": [
            "The selected tasks.1.priority is invalid."
          ]
        },
        "category": "validation"
      },
      "locations": [...],
      "path": [...],
      "trace": [...]
    }
  ]
}

errors[0].extensions.categoryvalidation となっているのが、 バリデーションエラーの証です。

errors[0].extensions.validation にエラーの詳細が入っており、 ここからエラーメッセージ等を取得することが出来ます。

# Check!

次のステップに進む前に以下の内容をもう一度確認しておきましょう。

  • altair から バリデーションルールに合わないデータを送信した際に、レスポンスからエラーメッセージが取得できますか?
  • altair 上で表示されるエラーメッセージは、入力フィールドの状態と正しく一致していますか?