Laravel 9中如何通过控制器模型实例添加关联计数查询?
问题原因及解决方法
为什么第二种写法不生效?
$buyer->withCount('tiers') 返回的是Eloquent查询构建器实例,而非已加载关联计数的Buyer模型实例。withCount是查询构建器的方法,作用是在发起数据库查询时预加载关联计数;但你已经通过路由模型绑定拿到了Buyer模型实例,直接调用withCount只会生成新的查询构建器,不会修改当前模型实例的属性。
正确的实现方式
方式一:使用loadCount方法(推荐)
loadCount是Eloquent模型实例的专属方法,用于给已加载的模型动态加载关联计数,执行后会在模型实例上自动添加tiers_count属性:
/** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show(Company $company, Buyer $buyer) { $this->authorize('view', Buyer::class); // 验证买家是否属于当前传入的公司(和原逻辑保持一致) if ($buyer->company_id !== $company->id) { return new ApiSuccessResponse(null, [ 'message' => 'Buyer not found or invalid buyer ID.' ], 404); } // 加载tiers关联计数 $buyer->loadCount('tiers'); return new ApiSuccessResponse($buyer); }
方式二:全局自动加载计数(按需使用)
如果项目中大多数场景都需要Buyer模型携带tiers计数,可以在Buyer模型中定义$withCount属性,这样每次查询Buyer时都会自动加载计数:
// app/Models/Buyer.php class Buyer extends Model { protected $withCount = ['tiers']; // 其他模型代码... }
这种方式无需在控制器中手动调用加载方法,适合全局需求场景。
补充说明
原代码中重新查询Buyer的逻辑虽然可行,但存在冗余:路由模型绑定已经帮你从数据库获取了Buyer实例,只需验证其归属公司,再加载计数即可,避免了重复查询数据库,性能更优。
内容的提问来源于stack exchange,提问作者Ryan H
相关产品推荐
相关产品推荐

