はじめに
この記事はプログラミング初学者による備忘録用の記事であり、また、少しでも他の初学者のお役に立てればと思い書いています。
今回は、アクセサを使用した際に発生したエラーProperty [xxxx] does not exist on this collection instance.
についての解決策を記録しておきたいと思います。
※新しいエラーが発生した場合、その都度追記していきます。
間違いなどがございましたら、ご指摘のほどよろしくお願い致します。
エラー文
Property [xxxx] does not exist on this collection instance.
エラー発生状況
テーブルの特定カラムを結合してデータを取得するためにアクセサを作成、コントローラで作成したアクセサを使用するとエラーが発生
エラーとなったコード
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Login extends Model
{
protected $appends = [
'login_date'
];
public function user(): BelongsTo
{
return $this->belongsTo('App\Models\User');
}//Models\UserではHasManyでリレーション
public function getLoginDateAttribute(): string
{
return $this->year . $this->month . $this->day;
//year,month,dayカラムを結合して'Y-m-d'の形で取得したかった
} //仕様の都合上、created_at,updated_atは使用していない
}
namespace App\Http\Controllers;
class UserController extends Controller
{
public function userData(string $name)
{
$user = User::where('name', $name)->first();
$logins = $user->logins;
$total_login = $samples->login_date->count();//エラー原因
dd($total_login);
//略
}
}
テーブル上の対象となるyear,month,dayカラムを結合して'Y-m-d'の形で取得後、日付重複なしでカウントしてログイン日数を取得したく、コントローラ側でアクセサで取得したデータをcount()でカウントしようとしたところ下記エラーが発生した。
Property [login_date] does not exist on this collection instance.
を読むと、エラー文は、アクセサを使い取得したコレクションインスタンスの中には、$key [login_date]は存在しないよと教えてくれている。(はず?)
解決策
色々と調べてみると、コレクションのgroupByメソッド
は指定したキーによりコレクションのアイテムをグループにまとめてくれることを知り、私が求めていた重複なしの形で日付データを取得できると思い使ってみると
class UserController extends Controller
{
public function userData(string $name)
{
//略
$total_login = $logins->groupBy('login_date');
dd($total_login);
/**
*dd()結果
* Illuminate\Database\Eloquent\Collection {#1479 ▼
#items: array:2 [▼
2021526 => Illuminate\Database\Eloquent\Collection {#1480 ▼
#items: array:5 [▶]
}
2021527 => Illuminate\Database\Eloquent\Collection {#1370 ▼
#items: array:4 [▶]
}
]
}
*エラーなく'Y-m-d'の形で日付データをまとめ、重複なしで取得できている
*/
}
}
求めていた形でデータを取得することができました。
あとは、エラー原因となっていたコードを、$total_login = $logins->groupBy('login_date')->count();
十することで日付データを重複なしでカウントすることができました。
おわりに
メモ:
モデルクラスでアクセサを設定する際は、getAttributeメソッドを上書きする方法はNGということを肝に銘じる。