You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel中使用ORM实现带whereIn的子查询

问题描述

我正在开发类社交网络功能,现有messages(消息)表、users(用户)表,以及存储用户关注关系的中间表,这些表的关联逻辑都能正常工作。我希望将以下SQL语句用Laravel ORM实现:

SELECT * FROM mensajes
WHERE user_id=1
OR user_id IN (SELECT seguido_id FROM seguidos WHERE user_id=1)

需求是获取当前用户的消息,以及其关注用户的消息。我现有方案可行但不够优雅,想改用子查询实现:

现有可行但不够优雅的代码

// 该关联关系返回当前用户关注的用户,可正常工作
$seguidos = auth()->user()->seguidos;

// 存储关注用户的ID数组
$seg = [];
foreach ($seguidos as $s) {
  array_push($seg, $s->id);
}
array_push($seg, auth()->user()->id);

// 获取这些用户的所有消息(包含自身)
$this->mensajes = Mensaje::whereIn('user_id', $seg)
  ->orderBy('created_at', 'desc')
  ->get();

尝试子查询但遇到疑问

$this->mensajes = Mensaje::where('user_id', auth()->user()->id)
  ->orWhereIn('user_id', function($query) {
    // ... 此处应如何编写?
    // $query = auth()->user()->seguidos->select('id');
    // 这样当然不行
    }
  ->orderBy('created_at', 'desc')
  ->get();
解决方案

你可以通过以下几种方式实现子查询写法:

方式一:直接构建子查询

在闭包内直接编写对应SQL的子查询逻辑:

$this->mensajes = Mensaje::where('user_id', auth()->user()->id)
    ->orWhereIn('user_id', function ($query) {
        // 子查询:获取当前用户关注的所有用户ID(对应seguido_id)
        $query->select('seguido_id')
              ->from('seguidos')
              ->where('user_id', auth()->user()->id);
    })
    ->orderBy('created_at', 'desc')
    ->get();

方式二:利用模型关联生成子查询

如果你的User模型已经定义了seguidos关联(比如hasMany或belongsToMany),可以直接借助关联的查询构造器生成子查询,注意要使用seguidos()(带括号,返回查询构造器实例)而非seguidos(不带括号,返回已加载的集合):

$this->mensajes = Mensaje::where('user_id', auth()->user()->id)
    ->orWhereIn('user_id', auth()->user()->seguidos()->select('id'))
    ->orderBy('created_at', 'desc')
    ->get();

方式三:合并自身ID与子查询

用union将自身ID和关注用户ID的子查询合并,统一用whereIn处理:

$this->mensajes = Mensaje::whereIn('user_id', function ($query) {
        $query->select('seguido_id')
              ->from('seguidos')
              ->where('user_id', auth()->user()->id)
              ->union(DB::raw("SELECT ".auth()->user()->id));
    })
    ->orderBy('created_at', 'desc')
    ->get();

补充:简化原有方案(非子查询但更优雅)

如果不想用子查询,也可以用pluck替代循环生成ID数组:

$userIds = auth()->user()->seguidos()->pluck('id')->push(auth()->user()->id);

$this->mensajes = Mensaje::whereIn('user_id', $userIds)
    ->orderBy('created_at', 'desc')
    ->get();

内容的提问来源于stack exchange,提问作者luisfer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 18:27:21