Laravel中withCount触发列不存在异常:unused_count字段未找到
问题解决:Eloquent scope中withCount导致的字段不存在异常
问题重现
在Eloquent模型中定义了包含withCount的scope方法,单元测试正常,但控制器调用时抛出异常:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'unused_count' in 'where clause' (SQL: select * from
couponswhereunused_count> 0)
模型代码如下:
public function unsed(): BelongsToMany { return $this->belongsToMany(User::class, 'user_coupon') ->wherePivot('discount', '=', 0); } public function scopeAvailable(Builder $query): Builder { return $query->where(function ($coupons) { return $coupons ->withCount('unused') ->where('quantity', '>', 0) ->orWhere('unused_count', '>', 0 ); }); }
错误原因及修复步骤
1. 关联方法名拼写错误
关联方法命名为unsed(),但withCount中调用的是'unused',Eloquent无法匹配到正确的关联关系,因此不会生成unused_count统计字段,直接导致WHERE子句找不到该列。
修复:将关联方法名改为unused(),与withCount的参数保持一致:
public function unused(): BelongsToMany { return $this->belongsToMany(User::class, 'user_coupon') ->wherePivot('discount', '=', 0); }
2. WHERE子句无法直接使用withCount生成的别名
即使修正拼写,withCount生成的unused_count是SELECT语句的别名,数据库执行WHERE子句时还未生成该别名,无法直接用于过滤。可通过以下两种方式解决:
方案一:使用having子句(简单场景适用)
调整scope逻辑,用having替代orWhere过滤统计字段,同时将withCount移到闭包外确保统计字段被加载:
public function scopeAvailable(Builder $query): Builder { return $query->withCount('unused') ->where(function ($coupons) { $coupons->where('quantity', '>', 0) ->orHaving('unused_count', '>', 0); }); }
方案二:子查询方式(复杂场景适用)
通过子查询直接计算未使用优惠券的数量,不依赖withCount生成的别名:
public function scopeAvailable(Builder $query): Builder { return $query->where(function ($coupons) { $coupons->where('quantity', '>', 0) ->orWhereExists(function ($subquery) { $subquery->select(DB::raw(1)) ->from('user_coupon') ->whereColumn('user_coupon.coupon_id', 'coupons.id') ->where('user_coupon.discount', 0) ->havingRaw('COUNT(*) > 0'); }); }); }
内容的提问来源于stack exchange,提问作者kazemm
相关产品推荐
相关产品推荐

