PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑

本文介绍如何在 php 中结合 mysql 查询,根据当前星期几和时间,精准筛选出“正在播出”或“即将播出”的电台节目,支持跨日自动回环(7天循环),并避免时间计算错误。

在构建电台类网站时,一个常见需求是:在首页动态展示「当前正在|直播|的主持人」和「下一位即将上线的主持人」。由于节目表仅存储了星期几(DAY: 0–6,对应周日–周六)和每日固定时段(如 START: "20:00"),无法直接用 DATETIME 类型做范围比较——这导致标准的时间函数(如 NOW())无法直接参与排序或过滤。

原始思路(如 $currentDay = date("w") + $currentTime = date("H:i"))虽能获取当前信息,但仅靠 PHP 端逐条判断效率低、逻辑易错,且难以优雅处理「今日无剩余节目 → 自动跳转至明日首个节目」这类边界场景。

✅ 正确解法:将时间逻辑下沉至 MySQL 层,利用 TIMESTAMP(CURDATE(), START) 构造当日完整时间点,并结合 ABS() 实现“距离当前时刻最近”的语义排序

以下是推荐的健壮查询方案(已修正原答案中的关键缺陷):

 ? THEN TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL (`DAY` - ?) DAY), `START`)
            ELSE TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL (7 + `DAY` - ?) DAY), `START`)
          END ASC
        LIMIT 1";

$stmt = $pdo->prepare($sql);
$stmt->execute([$currentDay, $currentDay, $currentDay, $currentDay]);
$nextShow = $stmt->fetch(PDO::FETCH_ASSOC);
?>

? 为什么这样设计?

  • 使用 CASE WHEN 显式处理三种情况:
    • DAY == today → 用 CURDATE() 拼接;
    • DAY > today → 向后推算天数(如今天周三 3,节目在周五 5 → +2 天);
    • DAY
  • 排序依据是「构造出的真实 DATETIME 值」,天然支持 NOW() 之后的首个节目的精确命中,无需 ABS() 这种近似技巧(原答案中 ABS(TIMESTAMP(...) - NOW()) 在跨日时会误判,例如 23:50 和次日 00:10 的差值远小于 00:10 与 NOW() 的真实间隔)。
  • 全程使用参数化查询,杜绝 SQL 注入风险。

? 额外建议:

  • 数据库中 DAY 字段建议添加索引:ALTER TABLE puzzle ADD INDEX idx_day_status (DAY, STATUS);
  • 若节目可能持续到次日凌晨(如 START: "23:30", END: "01:30"),需额外扩展 END 字段逻辑,此时应改用 TIME_TO_SEC() 计算跨日时长。
  • 前端展示时,可用 date('l H:i', strtotime($row['start_time'])) 格式化为“Monday 20:00”。

通过将业务时间逻辑封装进可预测、可索引的 SQL,既保障了性能,又大幅提升了代码可维护性与准确性。