Laravel动态复选框报错:试图获取非对象的'id'属性
嘿,咱们来一步步拆解你遇到的问题,这个错误的根源其实是几个容易忽略的小细节,下面逐个修复:
1. 控制器中超市数据的获取方式错误
你在ProductsController的create方法里用了pluck('name', 'id')->all(),这会返回一个键为ID、值为超市名称的关联数组,而非Supermarket模型对象的集合。所以在blade模板循环时,$supermarket是字符串(超市名称),不是对象,调用$supermarket->id自然会触发错误。
修改后的控制器代码:
// ProductsController.php public function create() { $categories = Category::pluck('name', 'id')->all(); // 去掉pluck,直接获取完整的模型对象集合 $supermarkets = Supermarket::all(); return view('admin.products.create', compact(['categories', 'supermarkets'])); }
如果你想保留pluck的精简写法,也可以这样调整(需同步修改blade模板):
// 返回[id => 超市名称]的关联数组 $supermarkets = Supermarket::pluck('name', 'id');
2. 模型关联的类名拼写错误
在Supermarket.php的关联方法里,你写的是App\Products,但你的模型类名是Product(单数),Laravel会找不到这个类,导致关联逻辑失效:
修改后的Supermarket模型:
// Supermarket.php class Supermarket extends Model { protected $fillable = [ 'name', 'url', ]; // 把App\Products改成App\Product(单数) public function products() { return $this->belongsToMany('App\Product'); } }
3. 清理Product模型中多余的字段(可选但推荐)
你的Product模型里注释掉的fillable数组包含了supermarket_id,但因为是多对多关联,这个字段不应该出现在products表中(多对多需要单独的中间表,比如product_supermarket)。建议把supermarket_id从fillable中移除,避免后续混淆。
4. 确保多对多中间表存在(关键)
Laravel多对多关联默认会按照模型名单数按字母顺序生成中间表名,你的场景下应该是product_supermarket表,需要确保这个表存在,结构示例:
CREATE TABLE product_supermarket ( product_id INT UNSIGNED NOT NULL, supermarket_id INT UNSIGNED NOT NULL, PRIMARY KEY (product_id, supermarket_id), FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE, FOREIGN KEY (supermarket_id) REFERENCES supermarkets(id) ON DELETE CASCADE );
如果你的中间表名不是这个,可以在关联方法里手动指定:
// Product.php public function supermarket() { return $this->belongsToMany('App\Supermarket', '你的自定义中间表名'); }
5. 修复blade模板的标签文本
原来的Form::label('supermarkets', $supermarket)会直接输出对象,改成输出超市名称更合理:
@foreach ($supermarkets as $supermarket) <div class="col-sm-3"> {!! Form::checkbox('supermarket_id[]', $supermarket->id) !!} {!! Form::label('supermarkets', $supermarket->name) !!} </div> @endforeach
如果用了之前pluck的精简写法,blade模板要改成这样:
@foreach ($supermarkets as $id => $name) <div class="col-sm-3"> {!! Form::checkbox('supermarket_id[]', $id) !!} {!! Form::label('supermarkets', $name) !!} </div> @endforeach
这样调整后,错误应该就能解决,多对多关联也能正常工作啦~
内容的提问来源于stack exchange,提问作者MattyO

