db::name() 配合 wheretime() 可按日/小时/分钟聚合查询,但需注意字段类型(仅 datetime/timestamp)、时区一致性及分组后数据类型(count(*) 返回字符串需强转),支持 'today'、'week'、'-2 hour' 等粒度,date_format 分组后排序须用原始时间字段。

直接用 Db::name() 配合 whereTime() 就能按日/小时/分钟做聚合查询,但必须注意字段类型、时区和分组后数据类型的陷阱——否则查出来全是 0 或报错。
whereTime() 支持哪些时间粒度
whereTime() 不是万能的,它只识别标准 DATETIME/TIMESTAMP 字段,且底层依赖 MySQL 的 DATE()、HOUR() 等函数。常见可用值有:'today'、'yesterday'、'week'、'month'、'year',也支持相对表达式如 '-1 day'、'-2 hour'。
- 字段必须是
DATETIME或TIMESTAMP类型,INT存时间戳会直接失效 - MySQL 严格模式下,
whereTime('created_at', 'week')默认从周日开始算,如需周一,得手动改 SQL 或用date_format -
'-2 hour'这类写法在低版本 MySQL(SELECT HOUR(NOW() - INTERVAL 2 HOUR) 验证
按小时分组统计调用量的正确写法
想看每小时接口调用分布,不能只靠 whereTime(),得配合 group() 和 date_format() 手动构造时间维度。ThinkPHP 原生不支持 GROUP BY HOUR(created_at) 这种裸函数,必须用 field() 显式声明。
- 正确示例:
Db::name('api_call_logs')->whereTime('request_time', '>=', '-24 hours')->group("date_format(request_time, '%Y-%m-%d %H:00:00')")->field("date_format(request_time, '%Y-%m-%d %H:00:00') as hour, count(*) as count")->select() - 错误写法:
->group('HOUR(request_time)')—— ThinkPHP 会把它当字段名处理,生成无效 SQL - 注意
date_format返回的是字符串,hour字段前端展示没问题,但排序要用ORDER BY request_time而不是hour,否则字符串排序会乱序(比如 "10:00:00" 排在 "2:00:00" 前)
count() 返回字符串?必须 int 强转
ThinkPHP 6+ 的 select() 和 value() 在聚合查询中,count(*) 结果默认是字符串类型,尤其在使用 PDO + MySQL 时,底层没设 PDO::ATTR_STRINGIFY_FETCHES = false,会导致 ECharts 渲染失败或图表空白。
- 前端接收前务必用
(int)$item['count']或intval($item['count'])转换,别信 PHP 自动类型推导 - 如果用
column('count')提取单列,返回的是字符串数组,得整体array_map('intval', $counts) - 更稳妥的做法是在 SQL 层强制转:
field('count(*) + 0 as count'),MySQL 会自动转为数字类型
真正容易被忽略的是时区:数据库用 UTC、PHP 用 Asia/Shanghai,whereTime('request_time', 'today') 查的其实是服务器本地时间对应的 UTC 区间,不是你看到的“今天”。上线前一定确认 date_default_timezone_set() 和 MySQL 的 time_zone 设置一致,否则凌晨两点的数据会跑进昨天的统计里。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











