Laravel 6.x エラー Property [カラム名] does not exist on this collection instance. リレーションでのエラー
制作環境
Windows 10
Laravel : 6.18.35
Laravel/ui : 1.0
Laravel-mix : 5.0.1
Bootstrap : 4.0.0
MDBootstrap : 4.19.1
chart.js : 2.9.3
XAMPP
PHP : 7.4.3
Visual Studio Code
はじめに
この記事はプログラミングをはじめたばかりの素人が、できたことをメモするのに利用しています。
内容には誤りがあるかもしれません。
独学でLaravelを勉強中なのですが、エラーでちょっとはまったので、解決方法とエラーの理由をまとめておきたいと思います。
当方は2月から2ヶ月間CodeCampのWebマスターコースを受講しました。
その最後の提出課題であるECサイトの作成を、個人的な要件を加えなら練習の為にLaravelで作成してみることにしました。
その最中に出たエラーです。
やりたい事
商品情報の入ったテーブルと、在庫数のテーブルから、全商品の情報とそれに紐付く在庫数を抽出して一覧表示する。
現在全体の形を作っているだけなので、テーブルは作成していますが中身は空です。
ここで使用するテーブル
Itemsテーブル
カラム名 | 項目 |
---|---|
id | 商品ID |
product_name | 商品名 |
price | 価格 |
img | 商品画像のパス |
status | 公開フラグ |
created_at | 作成日時 |
updated_at | 更新日時 |
Stocksテーブル
カラム名 | 項目 |
---|---|
id | 在庫ID |
item_id | 商品ID |
stock | 在庫数 |
created_at | 作成日時 |
updated_at | 更新日時 |
リレーション
関係は1対1になっています。
1対1はあまり使われていないようですが、CodeCampの内容に合わせています。
正直在庫数だけ分けている事に意味を感じないのですが、練習が目的なのでそのまま続けます。
エラー発生状況
管理者側の商品一覧ページを作成中に発生。
一覧に表示する内容としては、商品名、価格、商品画像、公開フラグ、在庫数を使用します。
下記はページのイメージで、商品一覧の下にテーブルで表示予定です。
エラー発生時にやっていたこと
各モデルに以下のように記述していました。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\Stock;
// 必ず追記
use Illuminate\Database\Eloquent\Relations\HasOne;
class Item extends Model
{
public function stock()
{
return $this->hasOne(Stock::class);
// useを使用しないなら以下の書き方でもOK
// return $this->hasOne('App\Models\Stock');
}
}
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\Item;
// 必ず追記
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Stock extends Model
{
protected $primaryKey = 'item_id';
public function item()
{
return $this->belongsTo(Item::class);
}
}
コントローラーには以下を記述(一部記述省略)。
use App\Models\Item;
public function index()
{
$data = Item::all()->stock;
return view('admin.home', compact('data'));
}
この状態でphp artisan serve で確認をした所、
エラー発生。
エラーの原因
コレクションインスタンスの中にstockが存在しない。
コントローラの記述に問題あり。
$data = Item::all()->stock;
この記述だと、Item::all()で取得したコレクションインスタンスの中からstockを引っ張り出そうとしている。
問題解決の為やってみたことと確認したこと
記述を以下に変更してみた(1)
記述を以下に変更
$data = Item::all();
結果:特に問題無く表示されるが、これでは在庫数が取れないので意味なし。ただ、テーブルにはアクセスできてるよう。
tinkerで確認
結果:テーブルに値が無いのでデータは空だが、Item::all();とStock::all();とする分にはコレクションが返ってきている。
リレーションの記述方法を色々と検索
find()を使用した記述は沢山あるが、それだと一つの商品の在庫数しかとれないので問題あり。
色々検索する中でwithを使う方法を発見。
参考サイト
https://qiita.com/June8715/items/4e0a8a64d51072af326c
https://www.yoheim.net/blog.php?q=20181104
記述を以下に変更してみた(2)
$data = Item::with('stock')->all();
結果:この記述は、やりたい事は伝わりそうだが間違い。
解決策
記述を以下に変更。
$data = Item::with('stock')->get();
結果:エラー解消。
ただ、実際にデータを入れて検証していないので、不具合があるかも。
今は形だけ作成しているので、そこはおいおい確認することに。
今回のイメージ
データ取得->コレクション化->リレション先のデータ取得 = エラー!
データ取得->リレション先のデータ取得->コレクション化 = OK!
Author And Source
この問題について(Laravel 6.x エラー Property [カラム名] does not exist on this collection instance. リレーションでのエラー), 我々は、より多くの情報をここで見つけました https://qiita.com/Charry/items/e2b44c76cecef02ee44e著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .