テーブル定義
table
users
id - integer
first_name - string
last_name - string
アクセサの定義
App/Models/User.php
/**
* ユーザーのフルネームの取得
*
* @return string
*/
public function getFullNameAttribute()
{
return "{$this->first_name} {$this->last_name}";
}
タイプ
User.graphql
type User{
id: ID!
first_name: String!
last_name: String!
fullName: String! ## キャメルケースでもスネークケースでも対応できる
}
リゾルバ
App/GraphQL/Queries/User.php
/**
* @param null $_
* @param array<string, mixed> $args
*/
public function __invoke($_, array $args)
{
$users = User::get();
return $users;
}
実行タイミング
- 取得処理を実行後toArrayを行う
User::get()->toArray();
- 取得処理を実行後対象の値を使用
$user User::first();
$user->fullName;
- graphqlのデータ取得時
query user{
id
first_name
last_name
fullName ## こちらを取得しようとしなければアクセサは実行されない
}
注意事項
- graphqlでのデータ取得時にはレコードごとにModelが実行される
例えば、アクセサにAPIのデータ取得処理や、重い処理を実装していた場合、get()やall()などで複数データを一気に取得する際、実行がレコード数になってしまうとレスポンス速度の低下が発生します。
graphqlでの取得時に対象のデータを取得しようとすると、レコードごとにModelが実行されるため以下のような処理を実行してもレコード分実行されてしまいました。
App/Models/User.php
+ public fullNames;
/**
* ユーザーのフルネームの取得
*
* @return string
*/
public function getFullNameAttribute()
{
+ if(isset($this->fullNames[$this->id])){
+ // すでにfullNamesに値が存在したらデータをそのまま返却する
+ return $this->fullNames[$this->id];
+ }
return "{$this->first_name} {$this->last_name}";
}
App/GraphQL/Queries/User.php
/**
* @param null $_
* @param array<string, mixed> $args
*/
public function __invoke($_, array $args)
{
+ // 先に必要なデータを取得して、ModelのfullNamesにセット
+ User::fullNames = $this->getFullNames();
$users = User::get();
return $users;
}
対応策
ここからは上記のようなことが発生した際に自分が実装した対応策になります。
※ もっとうまい回避方法がある気がするのですが、一旦このような方法で実装しました。(有識者の方良い方法があればご教授いただければと思います。)
こちらの方法だと、リレーション先の取得などが使用できなくなるため必要な場合は、Arrayの中に含めて上げる必要があります。
App/GraphQL/Queries/User.php
/**
* @param null $_
* @param array<string, mixed> $args
*/
public function __invoke($_, array $args)
{
$users = User::get();
+ //usersテーブルのカラムリストを取得
+ $columns = Schema::getColumnListing('users');
+ $userArray = [];
+ foreach($users as $key => $user){
+ // Userでの取得を単純な配列に変換(toArrayを使用するとそのタイミングでアクセサがレコードごとに実行されてしまうため注意)
+ foreach($columns as $column){
+ $userArray[$key][$column] = $user[$column];
+ }
+ $userArray[$key]['fullName'] = $userFullNames[$user->id];
+ }
- return $users;
+ return $usersArray;
}