多対多のリレーションが行われている際に、中間テーブルからなんらかのデータを取得したいときに使用するpivotメソッドがPHPStanの実行時にエラーが出てしまう。
エラー文
phpstan実行時にこの場合だと以下のエラーが発生します。
// コード
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
// エラー文
Access to an undefined property App\Models\User::$pivot.
原因
簡単にいうとPHPStanは静的解析ツールであり、LaravelのEloquentが提供しているpivotのような動的なプロパティについて認識することができないため。
対処法
次に紹介する1 or 2で解決できると思います。
1. getRelationValue()を使用する
foreach ($user->roles as $role) {
echo $role->getRelationValue('pivot')->created_at;
}
getRelationValueはmodelクラスがtraitで読み込んでいる
Illuminate\Database\Eloquent\Concerns\HasAttribute.phpに以下のように定義されています。
静的メソッドになるので、PHPStanでエラーになりません。
/**
* Get a relationship.
*
* @param string $key
* @return mixed
*/
public function getRelationValue($key)
{
// If the key already exists in the relationships array, it just means the
// relationship has already been loaded, so we'll just return it out of
// here because there is no need to query within the relations twice.
if ($this->relationLoaded($key)) {
return $this->relations[$key];
}
if (! $this->isRelation($key)) {
return;
}
if ($this->preventsLazyLoading) {
$this->handleLazyLoadingViolation($key);
}
// If the "attribute" exists as a method on the model, we will just assume
// it is a relationship and will load and return results from the query
// and hydrate the relationship's value on the "relationships" array.
return $this->getRelationshipFromMethod($key);
}
2. phpstan.neonにpivotのエラーに関するignore設定を追記する
includes:
- ./vendor/nunomaduro/larastan/extension.neon
parameters:
paths:
- app
# The level 9 is the highest level
level: 6
# 以下追記
# pivot関連のエラーをignore設定する
ignoreErrors:
- '#^Access to an undefined property .*::\$pivot\.$#'
もっと良い対処法があれば追記するので教えてください!