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

Laravel关联查询中如何基于new_notifications关联数据实现分页?

问题与解决方案

问题背景

需要查询角色ID为3、且关联的property_managements存在new_notifications的用户及关联数据,核心需求是基于new_notifications数据进行整体分页(而非对用户列表分页)。但尝试在关联闭包中使用paginate(10)无法实现预期效果,仍返回全部用户数据。

原查询代码:

$users = User::whereHas('role', function ($q) {
                $q->where('role_id', 3);
            })
            ->with(['property_managements.new_notifications.type'])
            ->with(['property_managements.new_notifications' => function ($q){
                $q->orderBy('notification_date', 'desc');
            }])
            ->with(['property_managements' => function ($q) {
                $q->whereHas('new_notifications');
            }])
            ->whereHas('property_managements.new_notifications')
            ->get();

无效的分页尝试:

->with(['property_managements.new_notifications' => function ($q){
    $q->orderBy('notification_date', 'desc')
      ->paginate(10);
}])

可行解决方案

方案1:以new_notifications为主模型实现全局分页

既然目标是对通知数据进行整体分页,直接从NewNotification模型出发构建查询是最直接的方案,同时关联所需的用户、物业及通知类型信息,过滤符合角色要求的用户:

$notifications = NewNotification::with([
        'property_management.user.role',
        'type'
    ])
    ->whereHas('property_management.user.role', function ($q) {
        $q->where('role_id', 3);
    })
    ->orderBy('notification_date', 'desc')
    ->paginate(10);

如果需要将分页后的通知按用户分组展示,可通过集合处理:

$groupedByUser = $notifications->groupBy('property_management.user.id');

方案2:按用户维度实现通知分页

若必须以User作为查询入口,且需要为每个用户单独分页其关联通知,可先获取符合条件的用户,再手动加载分页后的通知(注意配合预加载避免N+1查询):

  1. 获取目标用户:
$users = User::whereHas('role', fn($q) => $q->where('role_id', 3))
    ->whereHas('property_managements.new_notifications')
    ->with(['property_managements' => fn($q) => $q->whereHas('new_notifications')])
    ->get();
  1. 为每个用户加载分页通知:
$users->each(function ($user) {
    $user->load(['property_managements.new_notifications' => fn($q) => 
        $q->orderBy('notification_date', 'desc')->paginate(10)
    ]);
});

方案3:利用关联关系实现用户维度的通知分页(Laravel 8+)

在User模型中定义跨表关联allNotifications,然后通过该关联加载分页后的通知:

首先在User模型中添加关联:

public function allNotifications()
{
    return $this->hasManyThrough(
        NewNotification::class,
        PropertyManagement::class,
        'user_id',          // PropertyManagement表关联User的字段
        'property_management_id', // NewNotification表关联PropertyManagement的字段
        'id',               // User表主键
        'id'                // PropertyManagement表主键
    );
}

然后执行查询:

$users = User::whereHas('role', fn($q) => $q->where('role_id', 3))
    ->whereHas('allNotifications')
    ->with(['allNotifications.type' => fn($q) => 
        $q->orderBy('notification_date', 'desc')->paginate(10)
    ])
    ->get();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 06:52:41