在Laravel中使用关联作为子查询获取结果时报'is_liked'字段不存在
Laravel关联子查询筛选事件列表的调整方案
报错根因
- 查询构造器的
where方法默认仅解析当前主表(events表)的字段,你编写的where('like:is_liked', Auth::user()->id)会被框架直接映射为查询events表中的is_liked字段,由于该字段实际属于关联的like表,最终触发字段不存在的报错。 - 代码混淆了两个独立的关联操作逻辑:
with方法仅负责提前拉取关联表数据附加到主结果集,不会对主表返回结果做任何过滤,根本无法实现关联条件的筛选需求。
调整后的完整代码
$currentUser = Auth::user(); $events = Event::query() ->select('id', 'name', 'image', 'description', 'datetime', 'is_published') // 以关联为子查询,筛选出符合点赞条件的事件 ->whereHas('like', function ($query) use ($currentUser) { // 对齐你原判断逻辑:匹配is_liked字段为当前用户ID的记录 $query->where('is_liked', $currentUser->id); }) ->with([ // 预加载关联时限定数据范围,减少冗余查询 'like' => function ($query) use ($currentUser) { $query->select('id', 'id_event', 'id_user', 'is_liked', 'created_at') ->where('id_user', $currentUser->id); }, 'like.user:id,name,surname' ]) ->where('is_published', 1) ->paginate(6);
核心调整说明
- 用
whereHas替代原错误的跨表where写法:该方法会自动生成关联表的EXISTS子查询,将关联表的筛选条件落到子查询层面,完全不会出现关联表字段错映射到主表的问题,也匹配你“使用关联作为子查询筛选结果”的需求。 - 预加载逻辑做性能优化:给
like关联的预加载加闭包限定,只拉取和当前用户相关的点赞记录,避免全量查询所有用户的点赞数据造成的内存和带宽浪费。 - 移除
select语句中重复书写的description字段,减少不必要的字段查询开销。 - 可根据业务灵活调整筛选规则:如果需求是“展示所有已发布事件,仅附带当前用户对每个事件的点赞状态”,直接删除
whereHas部分的筛选代码即可,预加载逻辑会自动为每个事件匹配对应点赞记录,不会过滤主表结果。
内容的提问来源于stack exchange,提问作者sandri
相关产品推荐
相关产品推荐

