位置:首页 > PHP > ThinkPHP5.1日期循环如何排除周末日期

ThinkPHP5.1日期循环如何排除周末日期

时间:2026-08-17  |  作者:冻月看渠  |  阅读:0

whereTime本身没法直接把周末排除掉,这种场景通常得借助数据库原生函数来处理:MySQL 可以用WEEKDAY(),PostgreSQL 对应用EXTRACT(DOW),SQLite 则是strftime('%w')。更稳妥的做法,是把这类逻辑封装成模型作用域,方便后续复用;如果放到PHP层再过滤,不仅性能容易受影响,还可能把分页结果搞乱。除此之外,时区设置以及字段类型的差异,也都需要一并留意。

ThinkPHP5.1日期循环怎么排除周末

whereTime 无法直接排除周末,得用原生 SQL 或日期函数

ThinkPHP 5.1 的 whereTime 只支持预设时间范围(如 'today''week'),不提供工作日/周末过滤能力。想跳过周六、周日,必须绕过 whereTime,改用 whereRaw 或数据库原生函数。

  • MySQL 场景下,用 WEEKDAY():周一是 0,周日是 6,所以工作日是 WEEKDAY(create_time) BETWEEN 0 AND 4
  • PostgreSQL 用 EXTRACT(DOW FROM create_time):周日为 0,周一为 1,工作日即 EXTRACT(DOW FROM create_time) NOT IN (0,6)
  • SQLite 用 strftime('%w', create_time):周日为 '0',周六为 '6',可用 strftime('%w', create_time) NOT IN ('0','6')

示例(MySQL):

$list = Db::name('order')
->whereRaw('WEEKDAY(create_time) BETWEEN 0 AND 4')
->whereTime('create_time', '>=', '2026-08-01')
->select();

模型中封装 weekday 条件避免重复写 SQL

如果多处需要“非周末”查询,别在每个控制器里手写 whereRaw。在模型里加一个作用域方法更安全、易复用。

  • 在模型类中定义 scopeWeekday 方法,返回当前查询对象
  • 注意:TP5.1 不支持 scope 自动注入,需显式调用 ->scopeWeekday()
  • 不要在作用域里硬编码字段名,用 $this->getTable() 和传参方式增强兼容性

示例:

// 在 OrderModel.php 中
public function scopeWeekday($query, $field = 'create_time')
{
return $query->whereRaw("WEEKDAY({$field}) BETWEEN 0 AND 4");
}

// 使用时
$list = OrderModel::scopeWeekday('create_time')->whereTime('create_time', 'month')->select();

用 PHP 过滤 vs 数据库过滤,性能差一个数量级

有人图省事,在查出全量数据后用 date('N', $time) 判断是否为 1–5 再 array_filter,这在小数据量下看似可行,但极易翻车。

  • 数据库层过滤:10 万条记录,只扫描满足工作日条件的行,IO 和内存开销可控
  • PHP 层过滤:先拉满 10 万条,再遍历判断,PHP 进程内存暴涨,GC 压力大,响应延迟明显
  • TP5.1 的 Collection 不自动触发模型获取器,date('N') 还得手动转时间戳,逻辑更易出错

尤其当配合分页时,paginate() 是基于原始 SQL 的 LIMIT/OFFSET,PHP 过滤会破坏分页准确性——你看到的第一页可能全是周末数据,被 filter 掉后实际只剩两条。

注意时区和字段类型对 WEEKDAY 的影响

WEEKDAY() 等函数行为依赖字段存储类型和 MySQL 服务时区,容易踩坑。

  • 如果 create_timeINT 时间戳,MySQL 默认当它为 UTC 处理,WEEKDAY(FROM_UNIXTIME(create_time)) 才能正确对应本地星期几
  • 若字段是 DATETIME 且存的是本地时间,确认 MySQL 的 time_zone 设置与应用一致(如 SYSTEM'+08:00'
  • 测试方法:在 phpMyAdmin 或命令行执行 SELECT create_time, WEEKDAY(create_time), DAYNAME(create_time) FROM order LIMIT 5;,比对结果是否符合预期

真正麻烦的不是写一行 whereRaw,而是忘记时区或字段类型导致“明明是周一却判成周末”。上线前务必用真实数据验证,别只测今天。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多