在使用Laravel×GraphQL(Lighthouse)时,获取访问器的值时执行访问器的时机
表格定义
users
id - integer
first_name - string
last_name - string
アクセサ的定义
/**
* ユーザーのフルネームの取得
*
* @return string
*/
public function getFullNameAttribute()
{
return "{$this->first_name} {$this->last_name}";
}
类型 (type)
type User{
id: ID!
first_name: String!
last_name: String!
fullName: String! ## キャメルケースでもスネークケースでも対応できる
}
决策者
/**
* @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が実行されるため以下のような処理を実行してもレコード分実行されてしまいました。
+ 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}";
}
/**
* @param null $_
* @param array<string, mixed> $args
*/
public function __invoke($_, array $args)
{
+ // 先に必要なデータを取得して、ModelのfullNamesにセット
+ User::fullNames = $this->getFullNames();
$users = User::get();
return $users;
}
应对方法 (duì yì fǎ)
当发生像上述情况时,以下是我实施的对应措施。
※ 我觉得可能还有更好的避免方法,但暂时先用这种方法来实施。(如果有专业人士知道更好的方法,请教授一下。)
使用这种方法时,由于无法使用关联获取等功能,如果有需要,必须将其包含在数组中。
/**
* @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;
}