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

Laravel下按多时段筛选过期房源的SQL返回结果错误如何修复

问题原因

你的现有逻辑存在漏洞:仅在高优先级的to_date_*字段(to_date_3/to_date_2)非空且已过期时才中断判断,若高优先级字段非空但未过期,代码会继续向下判断低优先级的to_date字段,只要低优先级字段过期就会把房源加入结果,完全违背了「只判断最新的非空to_date_*字段」的规则。

以你给出的示例为例,假设当前时间为2021-08-22:

  • id=2的最新非空to_date是to_date_2=2021-08-25(未过期),本不应返回,但现有代码判断to_date_2未过期后,继续判断to_date_1=2021-08-10(已过期),就错误把id=2加入了结果
  • id=1的最新非空to_date是to_date_3=2021-09-15(未过期),本不应返回,但现有代码判断to_date_3未过期后,继续判断低优先级字段,最后因to_date_1过期错误加入结果

修复方案

方案1:修改集合过滤逻辑(快速适配现有代码)

调整判断规则:只要高优先级to_date_*字段非空,无论是否过期都只判断该字段,判断后直接终止逻辑,不再查看更低优先级的字段:

$now = \Carbon\Carbon::now()->toDateString();
$listings = $all_listings->filter(function ($lis) use ($now) {
    // 非空就只判断最高优先级的to_date_3
    if (!is_null($lis->to_date_3)) {
        return $lis->to_date_3 < $now;
    }
    // to_date_3为空才判断to_date_2
    if (!is_null($lis->to_date_2)) {
        return $lis->to_date_2 < $now;
    }
    // 前两个都为空才判断to_date_1
    return $lis->to_date_1 < $now;
});

方案2:SQL层直接过滤(更推荐)

你原来的写法是先分页再过滤,会导致每页实际返回数量不足(比如分页配置10条,过滤后只剩3条),直接在查询阶段过滤可以避免这个问题,性能也更高:

$now = \Carbon\Carbon::now()->toDateString();
$all_listings = Listing::query()
            ->where('vendor_id', $vendor->id)
            ->where('is_deleted', 0)
            ->where('is_published', 1)
            ->where('is_approved', 1)
            ->where('lease_term', '!=', 'long_term')
            // 核心过期判断逻辑
            ->whereRaw('
                CASE
                    WHEN to_date_3 IS NOT NULL THEN to_date_3 < ?
                    WHEN to_date_2 IS NOT NULL THEN to_date_2 < ?
                    ELSE to_date_1 < ?
                END = 1
            ', [$now, $now, $now])
            ->orderBy('created_at', 'desc')
            ->paginate(10);

修改后查询出来的结果直接符合要求,不需要再二次遍历过滤。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 21:42:00