在使用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;
}
广告
将在 10 秒后关闭
bannerAds