whereTime() 专用于匹配 datetime 字段的时分秒部分,忽略日期,生成 TIME() 等 SQL 表达式;支持字符串如 '09:00' 和比较操作符,但需配合 whereDate() 实现“今天某时刻”的精确查询。

whereTime() 只匹配时间部分,不关心日期
当你要查“今天下午3点发的消息”或“每天 09:00 执行的任务”,但数据库里存的是 datetime(比如 "2024-05-20 15:30:00"),直接用 where() 等于某个时间会失败——因为日期部分不确定。这时候 whereTime() 就是专为解决这个问题设计的。
它底层生成 SQL 的 HOUR()、TIME() 或 CAST(... AS TIME) 表达式,只比对 HH:MM:SS 部分:
$users = User::whereTime('created_at', '09:00:00')->get();
// 生成类似:WHERE TIME(created_at) = '09:00:00'
- 支持字符串格式:
'09:00'、'14:30:15'、'00:00:00' - 也支持比较操作符:
whereTime('starts_at', '>=', '08:00') - 注意:MySQL 5.6+ 和 PostgreSQL 支持良好;SQLite 会降级为字符串截取,结果可能不一致
whereDate() 和 whereTime() 别混用,它们管不同字段
whereDate() 看的是年月日(YYYY-MM-DD),whereTime() 只看时分秒(HH:MM:SS)。两者互不影响,也不能互相替代。
常见误用场景:
立即学习“PHP免费学习笔记(深入)”;
- 想查“所有在 10:00–11:00 之间创建的记录”,却写了
whereDate('created_at', '>=', '10:00')→ 错,whereDate不接受时间字符串 - 想查“今天早上 9 点的数据”,却只用
whereTime('created_at', '09:00')→ 错,它会捞出历史上所有 9 点的数据,不限今天
正确组合方式:
User::whereDate('created_at', today())
->whereTime('created_at', '>=', '09:00')
->whereTime('created_at', '<', '10:00')
->get();
whereBetween() 对时间部分无效,别指望它自动拆解
whereBetween('created_at', ['09:00', '17:00']) 是错的:Eloquent 会把两个字符串当成完整 datetime 去解析(如变成 '0000-00-00 09:00:00'),结果永远为空或意外匹配。
真正要按“时间段内的时间部分”筛选,必须显式拆成两个 whereTime() 条件:
- ✅ 正确:
whereTime('starts_at', '>=', '09:00')->whereTime('starts_at', ' - ❌ 错误:
whereBetween('starts_at', ['09:00', '17:00']) - ⚠️ 注意:闭区间边界需自行判断是否含秒,比如
'17:00:00'和'16:59:59'在高精度场景下行为不同
自定义时间部分查询:用 whereRaw 避开 Eloquent 封装限制
当需要提取小时、分钟单独判断(比如“只查上午时段(HOUR < 12)”或“整点触发(MINUTE = 0)”),whereTime() 就不够用了。
这时直接上 whereRaw() 更灵活、更可控:
// 查所有上午创建的用户(HOUR(created_at) < 12)
User::whereRaw('HOUR(created_at) < ?', [12])->get();
// 查分钟数为 0 的记录(整点)
User::whereRaw('MINUTE(created_at) = 0')->get();
// PostgreSQL 写法略有不同:EXTRACT(HOUR FROM created_at)
User::whereRaw("EXTRACT(HOUR FROM created_at) >= ?", [9])->get();
- 注意参数绑定(用
?占位符)防止 SQL 注入 - 数据库函数名因驱动而异:
HOUR()是 MySQL,PostgreSQL 用EXTRACT(),SQL Server 用DATEPART(hh, ...) - 这类写法绕过了 Eloquent 的模型时间转换逻辑(比如
$casts中的datetime),直接走原始字段值
时间部分匹配看似简单,但日期类型、数据库方言、边界语义三者一叠加,很容易漏掉某一天或多捞几条。实际写的时候,先确认字段类型是 datetime 还是 time,再决定用 whereTime() 还是 whereRaw(),比硬套文档示例更可靠。



















