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

Laravel Eloquent条件式预加载实现:仅加载非当前用户的发送方与接收方

解决方案:Laravel Eloquent 条件式预加载

刚好碰到过类似的需求,Laravel 的 Eloquent 预加载功能支持通过闭包来添加条件,完美满足你要的「仅当指定字段不等于当前用户 ID 时才加载关联」的需求。

修改后的查询代码

首先,我们可以直接在 with() 方法中传入闭包来过滤关联模型,同时优化一下原来的 where 逻辑(用闭包包裹避免后续添加条件时出现逻辑冲突):

$userId = Auth::user()->id;

$inboxs = Inbox::select("id", "sender_id", "receiver_id")
    ->where(function ($query) use ($userId) {
        $query->where('sender_id', $userId)
              ->orWhere('receiver_id', $userId);
    })
    ->with(['sender' => function ($query) use ($userId) {
        // 仅当 sender 的 ID 不等于当前用户时加载该关联
        $query->where('id', '!=', $userId);
    }])
    ->with(['receiver' => function ($query) use ($userId) {
        // 仅当 receiver 的 ID 不等于当前用户时加载该关联
        $query->where('id', '!=', $userId);
    }])
    ->orderBy('id', 'desc')
    ->paginate(5);

代码解释

  1. 优化查询条件:把原来的 where + orWhere 包裹在闭包里,确保后续如果添加其他 where 条件时,不会破坏原有的逻辑(避免出现 (A OR B) AND C 变成 A OR (B AND C) 的错误)。
  2. 条件预加载:在 with() 的闭包中,我们给关联查询添加了 where('id', '!=', $userId) 的条件。这样:
    • 如果当前 inbox 的 sender_id 等于当前用户 ID,那么 sender 关联的查询会返回空结果,Eloquent 会自动把该 inbox 对象的 sender 属性设为 null;
    • 如果 sender_id 不等于当前用户 ID,就会正常加载对应的用户数据。
  3. 性能友好:这种方式依然是「预加载」,只会执行两次额外的关联查询(一次查所有符合条件的 sender,一次查所有符合条件的 receiver),不会出现 N+1 查询问题。

可选优化:更简洁的写法(PHP 7.4+)

如果你用的是 PHP 7.4 及以上版本,可以用短闭包让代码更简洁:

$userId = Auth::id();

$inboxs = Inbox::select("id", "sender_id", "receiver_id")
    ->where(fn($query) => $query->where('sender_id', $userId)->orWhere('receiver_id', $userId))
    ->with(['sender' => fn($q) => $q->where('id', '!=', $userId)])
    ->with(['receiver' => fn($q) => $q->where('id', '!=', $userId)])
    ->orderBy('id', 'desc')
    ->paginate(5);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 08:02:42