📖

Laravel アクセサを使用したらUndefined Propertyが返ってきた件

2022/02/03に公開

環境

Laravel 6.20.32

実現したいこと

アクセサを使用してデータ整形を行う
今回、整形したいデータはscheduled_start_timeカラム

実装

まず、アクセサを使用するにはモデルにgetFooAttributeの形のメソッドを作成すること。
(アッパーキャメルケース)

public function getScheduledStartTimeAttribute()
{
    return $this->scheduled_start_time;
}

そしてビューの方は $video->scheduled_start_timeの形で記述(スネークケース)
この記述で書くことでLaravel側で勝手にアクセサを呼んでくれます。

これでデータ自体は取得できるかと思いきや・・・

そんなプロパティはないよと怒られる。。。
調べていたら同じエラーに遭遇している方の記事に辿り着いた
Undefined property, but other columns do work

そのやり取りの中でこのように書いてあった

Your code is not working because return $this->primary_column; this statement in your accessor is causing an infinite loop as the accessor is called every time when primary_column is being accessed. In your case when you access the primary_column the accessor is called and in accessor, you are again accessing the primary_column which again calls the accessor itself and the loop continues so on.

要約すると、アクセサ名とプロパティ名が同一になっていてprimary_columnにアクセスする度に
アクセサに呼び出しており無限ループを引き起こしている。
そもそもデータを整形するためにアクセサを使用するのだから、プロパティを呼び出すだけなら
$video->scheduled_start_timeでいいはず。。
(普通に考えたらLaravel側もプロパティなのかアクセサなのか判断できない)

なので以下のようにする必要がある

public function getStartTimeAttribute()
{
    return $this->scheduled_start_time;
}

そしてビュー側を $video->start_timeでアクセスすると取得できる

上記メソッド名は一例だが、アクセサのメソッド名は柔軟に対応しているみたい
【Laravel】アクセサの使い方

でも、今回のやり方でもアクセサにパラメーターを送ることで一応取得はできるらしい

The solution is to pass a value as a parameter in the accessor. Eloquent will automatically map this parameter to primary_column value, now you can do whatever you want to do with the value.

public function getScheduledStartTimeAttribute($value)
{
    return $value;
}

で、$video->scheduled_start_timeでアクセスすると、、

取得できた
でも明らかに本来の使い方ではなさそう。。
どういう場面で使用するんだろう

引用

Undefined property, but other columns do work
【Laravel】アクセサの使い方

Discussion