在使用 PHP 的 PDO 操作数据库时,PDOStatement::fetchObject() 方法非常方便,它可以将查询结果直接映射为一个对象。然而,当数据库字段中包含(如 DATETIME、TIMESTAMP 类型)时,直接使用 fetchObject 可能会遇到一些问题,比如日期字段被当作普通字符串处理,导致后续格式化和比较变得麻烦。
本文将讲解如何在使用 fetchObject 时,正确地处理这些日期时间字段,并给出实用示例。
假设有一个用户表 users,结构如下:
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
created_at DATETIME NOT NULL
);
插入一条数据:
INSERT INTO users (name, created_at) VALUES ('Alice', '2025-04-27 14:30:00');
用 fetchObject 获取数据:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $pdo->query('SELECT * FROM users WHERE id = 1');
$user = $stmt->fetchObject();
echo $user->created_at;
?>
输出的是一段普通字符串:
2025-04-27 14:30:00
如果想要对 created_at 进行时间加减、格式化等操作,就不得不手动用 DateTime 类转换,非常不优雅。
有两种常见方式来优雅地处理:
在拿到对象后,立即将日期字段转成 DateTime 对象。
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $pdo->query('SELECT * FROM users WHERE id = 1');
$user = $stmt->fetchObject();
if ($user && isset($user->created_at)) {
$user->created_at = new DateTime($user->created_at);
}
// 现在可以直接使用 DateTime 方法
echo $user->created_at->format('Y年m月d日 H:i:s');
?>
虽然这种方式简单,但每次都要手动转换,如果表结构复杂或者字段多,维护成本会增加。
创建一个实体类,定义好对应的属性类型,并在构造函数中自动处理日期时间。
<?php
class User
{
public int $id;
public string $name;
public DateTime $created_at;
public function __construct()
{
// 需要将原本的字符串 created_at 转成 DateTime 对象
if (is_string($this->created_at)) {
$this->created_at = new DateTime($this->created_at);
}
}
}
?>
使用 fetchObject 时指定类名:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $pdo->query('SELECT * FROM users WHERE id = 1');
$user = $stmt->fetchObject(User::class);
echo $user->created_at->format('Y-m-d H:i:s');
?>
这样做的好处是:
代码更清晰
避免遗漏字段处理
对象结构更规范,方便 IDE 自动补全
适合更大型的项目或长期维护
如果你的 PHP 版本支持,可以结合 属性类型声明,例如 PHP 8.0 引入的 constructor property promotion,进一步简化实体类写法。
同时,确保数据库返回的字段格式始终符合 ISO 标准(YYYY-MM-DD HH:MM:SS),以免 DateTime 解析失败。
使用 PDOStatement::fetchObject() 时,直接返回的日期时间字段是字符串。如果需要优雅处理,建议:
小项目可在取出后手动转换为 DateTime
大项目或规范开发中,强烈推荐使用自定义实体类
通过合理设计实体类,可以极大提升代码的健壮性和可维护性。
如果你想了解更多关于 PDO 使用技巧,可以参考官方文档。