商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Laravel 查询中处理可空结束日期的动态范围筛选

Laravel 查询中处理可空结束日期的动态范围筛选

  发布于2026-07-20 阅读(0)

扫一扫,手机访问

本文讲解如何在 Lara vel 中正确构建查询条件,使记录满足“大于等于开始时间、且仅当结束时间存在时小于等于结束时间”的逻辑,避免因 end_at 为 NULL 导致查询失效。

聊一个业务里经常碰到的“小坑”——时间范围筛选,但结束日期偏偏是可空的。比如活动有效期、价格策略、权限有效期这类场景,通常会有个必填的start_at,和一个可选的end_at。如果end_at为空,表示长期有效;不为空,那就得严格落在 [start_at, end_at] 这个闭区间内。听起来简单,写查询的时候却容易翻车。

直接上 whereBetween()?不行,因为那个方法默认两端都得非空,给个null进去,SQL 直接报错或者出假结果。写两个where条件固定住?更糟——where('end_at', '>=', $effectiveDate) 碰上 end_at 是 NULL,SQL 里 NULL 跟任何值比较都返回 UNKNOWN,整行记录就被过滤掉了,那些本该长期有效的记录全没了。

正确做法是条件化查询,用闭包把“或”逻辑包装进去。看这段代码:

$effectiveDate = '2022-04-06 23:34:00';
GroupExtras::query()
    ->select('group_extras.*')
    ->join('groups', 'group_extras.group_id', '=', 'groups.id')
    ->where('group_extras.start_at', '<=', $effectiveDate)
    ->where(function ($query) use ($effectiveDate) {
        // 分支一:end_at 为 NULL → 视为无限期,无需额外限制
        $query->whereNull('group_extras.end_at')
              // 分支二:end_at 非 NULL → 必须 >= effectiveDate
              ->orWhere(function ($sub) use ($effectiveDate) {
                  $sub->whereNotNull('group_extras.end_at')
                      ->where('group_extras.end_at', '>=', $effectiveDate);
              });
    })
    ->orderBy('group_extras.value')
    ->first();

关键逻辑拆开看:

  • 主条件 start_at <= $effectiveDate 先把所有已生效的记录筛出来。
  • 匿名闭包里面,用 whereNull() 匹配无结束日期的行,再通过 orWhere() 嵌套一个子条件:只有那些有结束日期且还没过期的才保留。这样两个分支合并,正好覆盖“长期有效”和“有限期”两种场景。
  • 切记不要在 where() 里直接写 end_at >= ? 然后传 NULL,SQL 里 NULL 比较返回 UNKNOWN,行会被排除,这是最隐蔽的坑。

另外有几个小提醒:

  • 别用 whereBetween('column', [$start, $end]),它底层生成 BETWEEN $start AND $end,$end 是 null 时直接非法。
  • 如果项目用的是 MySQL 5.7+ 严格模式,建议用 Carbon 把时间格式化成标准 Y-m-d H:i:s 字符串,或者显式用 DB::raw() 处理,避免隐式转换出问题。
  • 数据量大的表,记得在 start_atend_at 上建联合索引,比如 INDEX(start_at, end_at),这个查询的效率会好很多。

这个方案写起来语义清晰,也兼容主流数据库,算是 Lara vel 里处理“半开放时间区间”的标准思路了。下次遇到类似需求,直接套用这个闭包模板就行,不用再纠结 NULL 导致的“幽灵过滤”。

本文转载于:https://www.php.cn/faq/2323544.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注