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

Laravel中如何实现基于isOldUser方法的查询作用域?

Laravel User模型老用户筛选查询作用域实现方案

首先要明确:查询作用域是用来构建批量数据库查询的,不能直接复用单个用户的isOldUser方法(因为它依赖缓存且针对单实例),需要把老用户的判断条件转换成数据库层面的关联存在性检查。

实现思路

老用户的核心判断逻辑是同时满足两个条件:

  1. 用户存在创建时间早于3个月前的治疗方案
  2. 用户存在符合以下要求的预约记录:
    • 预约时间早于3个月前
    • 状态为「到店就诊」
    • 已完成就诊
    • 类型为「就诊」

查询作用域需要根据传入的布尔值,分别筛选符合/不符合上述条件的用户。

代码实现

假设User模型已定义以下关联(请根据实际模型关联调整):

// User.php
public function treatments()
{
    return $this->hasMany(Treatment::class); // 治疗方案关联
}

public function appointments()
{
    return $this->hasMany(Appointment::class); // 预约记录关联
}

添加查询作用域:

// User.php
public function scopeIsOldUserFilter($query, bool $isOldUser)
{
    $threeMonthsAgo = now()->subMonths(3);

    if ($isOldUser) {
        // 筛选同时满足两个条件的老用户
        $query->whereHas('treatments', function ($treatmentQ) use ($threeMonthsAgo) {
            $treatmentQ->where('created_at', '<', $threeMonthsAgo);
        })
        ->whereHas('appointments', function ($appointmentQ) use ($threeMonthsAgo) {
            $appointmentQ->where('appointment_time', '<', $threeMonthsAgo)
                ->where('status', '到店就诊') // 替换为你的实际字段值
                ->where('is_completed', true) // 替换为你的实际字段/值
                ->where('type', '就诊'); // 替换为你的实际字段值
        });
    } else {
        // 筛选不满足老用户条件的用户:要么无符合条件的治疗方案,要么无符合条件的预约
        $query->where(function ($subQ) use ($threeMonthsAgo) {
            $subQ->whereDoesntHave('treatments', function ($treatmentQ) use ($threeMonthsAgo) {
                $treatmentQ->where('created_at', '<', $threeMonthsAgo);
            })
            ->orWhereDoesntHave('appointments', function ($appointmentQ) use ($threeMonthsAgo) {
                $appointmentQ->where('appointment_time', '<', $threeMonthsAgo)
                    ->where('status', '到店就诊')
                    ->where('is_completed', true)
                    ->where('type', '就诊');
            });
        });
    }

    return $query;
}

使用示例

// 获取所有老用户
$oldUsers = User::isOldUserFilter(true)->get();

// 获取所有非老用户
$nonOldUsers = User::isOldUserFilter(false)->get();

注意事项

  1. 请根据你的数据库字段名,替换代码中status、is_completed等字段的实际值
  2. 为了优化查询性能,建议给以下字段添加组合索引:
    • treatments(user_id, created_at)
    • appointments(user_id, appointment_time, status, is_completed, type)
  3. 查询作用域无法复用单用户的缓存逻辑,因为批量查询需要直接操作数据库;如果需要缓存批量结果,可以在调用作用域后自行处理缓存。

内容的提问来源于stack exchange,提问作者M a m a D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 10:57:10