You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PDO中日期字符串转对象报错求助:Undefined变量与foreach参数无效

修复PDO类中日期转换的错误问题

我来帮你拆解一下遇到的这几个错误,然后一步步搞定代码的问题:

错误原因分析

  1. Notice: Undefined variable: dates
    你在构造函数里写了foreach($this->$dates AS $date),这里的$dates是一个没有定义的局部变量。你实际要访问的是类的protected $dates属性,应该写成$this->dates(去掉变量名前面的第二个$)。

  2. Notice: Undefined property: User::$ 和 Warning: Invalid argument supplied for foreach()
    这两个错误都是第一个问题导致的连锁反应:因为$dates未定义,$this->$dates会被PHP解析为访问一个空字符串对应的属性,这个属性肯定不存在,所以foreach拿到的是无效参数,直接报错。

  3. 隐藏的坑:PDO的FETCH_CLASS执行顺序
    即使你修复了上面的问题,代码还是会出错——因为PDO默认是先调用类的构造函数,再把查询结果的属性赋值给对象。也就是说,你的构造函数执行时,$this->created还没有被赋值,这时候尝试用它创建DateTime对象会抛出新的错误。

修复后的完整代码

<?php
ini_set('display_errors', 'On');
// Create a class called user
class User {
    protected $dates = [
        'created',
    ];
    // This is supposed to convert my dates from a string to an object
    public function __construct() {
        // 修复:访问类属性$this->dates,而非未定义的局部变量$dates
        foreach($this->dates AS $date) {
            // 增加判断,避免属性不存在时出错
            if (isset($this->{$date})) {
                $property = $this->{$date};
                $this->{$date} = new DateTime($property);
            }
        }
    }
    // Adding a public function that will be available outsite of the class
    public function getFullName() {
        return "{$this->firstname} {$this->lastname}";
    }
}
$db = new PDO('mysql:host=127.0.0.1;dbname=pdo', 'root', '');
$req = $db->query("SELECT * FROM users");
// 修复:添加PDO::FETCH_PROPS_LATE,让PDO先赋值属性再执行构造函数
$req->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'User');
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>PDO</title>
</head>
<body>
<?php while($user = $req->fetch()): ?>
    <div class="user">
        <h4><?php echo $user->getFullName(); ?></h4>
        <p>Registered on <?php echo $user->created->format('d M Y'); ?></p>
        <!-- 现在可以正常工作了 -->
    </div>
<?php endwhile; ?>
</body>
</html>

关键修改说明

  • 构造函数的循环变量:把$this->$dates改为$this->dates,正确访问类的属性。
  • PDO获取模式:添加PDO::FETCH_PROPS_LATE选项,这个选项会让PDO先把查询结果的所有属性赋值给User对象,再调用构造函数,这样构造函数执行时$this->created已经有值了。
  • 增加属性存在判断:避免如果数据库中某个日期字段为空或者不存在时,代码抛出新的错误,提升代码健壮性。

现在你再运行代码,应该就能正常把日期字符串转为DateTime对象,并且正确格式化显示了。

内容的提问来源于stack exchange,提问作者James Bissick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:56:19