php通过查询数据库获取expires_at字段值,转为datetime对象后与当前时间比较判断是否过期,需注意时区一致、NULL处理及字段类型为datetime/timestamp。

PHP 怎么读取栏目过期时间(expires_at 字段)
栏目过期时间不是 PHP 内置概念,而是业务逻辑中常见的字段,通常存于数据库(如 mysql)的栏目表里,字段名可能是 expires_at、expire_time 或 valid_until。PHP 本身不“知道”栏目是否过期,得你主动查、解析、比对。
典型做法是:查出该栏目的 expires_at 值 → 转成时间戳或 DateTime 对象 → 和当前时间比较。
- 确保字段类型是
DATETIME或TIMESTAMP,避免用字符串存时间(如"2025-03-15"不带时分秒易出错) - 注意时区:PHP 默认时区(
date_default_timezone_set())和数据库时区要一致,否则now()和strtotime()结果会偏差 - 如果字段允许为
NULL,必须先判断,否则strtotime(null)返回false,后续比较可能意外通过
用 pdo 查询并判断栏目是否已过期
这是最常用且安全的方式,避免 SQL 注入,也方便处理 NULL 和时区。
$stmt = $pdo->prepare("SELECT id, title, expires_at FROM categories WHERE id = ?"); $stmt->execute([$catId]); $category = $stmt->fetch(PDO::FETCH_ASSOC); if (!$category || !$category['expires_at']) { // 栏目不存在,或未设置过期时间 → 视为永不过期 $isExpired = false; } else { $expireTime = new DateTime($category['expires_at']); $now = new DateTime(); // 自动使用 date_default_timezone_set() 设定的时区 $isExpired = $expireTime < $now; }
关键点:
立即学习“PHP免费学习笔记(深入)”;
-
new DateTime($category['expires_at'])能自动识别标准日期格式(如"2025-04-10 18:30:00"),比strtotime()更健壮 - 不要直接拼接 SQL,比如
"WHERE expires_at —— 这会让逻辑耦合在 SQL 层,不利于单元测试和调试 - 如果需要批量判断多个栏目,建议一次性查出所有
expires_at,再用 PHP 循环判断,别在循环里反复查库
常见错误:把时间戳当字符串比较
有人会这样写:
$row['expires_at'] < time() // ❌ 危险!$row['expires_at'] 是字符串 "2025-04-10 12:00:00"
PHP 会把字符串转成整数(从左开始取数字),"2025-04-10..." → 2025,永远小于 time()(约 17亿),导致“所有栏目都显示已过期”。
正确做法只有两种:
- 用
DateTime对象做比较(推荐) - 用
strtotime($row['expires_at'])转成时间戳再比(但需检查返回值是否为false)
别图省事跳过类型转换。
缓存场景下怎么保证过期判断实时?
如果栏目数据被 redis 或 APCu 缓存了,而 expires_at 又是动态变化的,不能只缓存栏目基本信息,还得把过期判断逻辑移出缓存层。
- 缓存栏目元数据(
id、title、expires_at),但每次读缓存后仍要执行时间比对 - 不要缓存
is_expired的布尔结果 —— 它随时间推移自动翻转,缓存失效策略很难设计 - 如果性能敏感,可缓存“下次检查时间”,比如过期前 5 分钟再查一次 DB,但实现复杂,多数项目没必要
真正容易被忽略的是:缓存键没包含时区信息,或者本地开发环境用 Asia/Shanghai,线上用 UTC,会导致同一份缓存数据在不同环境判断结果相反。