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

PDO::FETCH_CLASS获取私有属性对象后json_encode返回空对象的问题咨询

问题解答

为什么json_encode处理后只显示空对象?

json_encode() 默认仅序列化对象的公共属性,私有属性不会被纳入序列化范围。而var_dump作为调试工具,会绕过PHP的访问控制权限,展示对象的所有属性,这就是你看到属性有值但JSON为空的原因。

另外你的__get()方法存在错误:该魔法方法要求返回对应属性的值,但你定义的返回类型是void,这会导致即使通过$obj->name访问私有属性也无法获取内容,进一步影响序列化结果。

解决方法

  • 推荐方案:实现JsonSerializable接口,自定义序列化逻辑,明确指定要序列化的属性:
class Product implements JsonSerializable
{
    private string $id;
    private string $name;
    private int $price;

    // 保留原有方法

    public function jsonSerialize(): mixed
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'price' => $this->price,
        ];
    }
}

之后再调用json_encode()就能得到包含所有属性的JSON。

  • 临时方案:强制类型转换(仅适合属性名与数据库列名完全匹配的场景):
$jsonData = json_encode((array)$productList);

如何无需显式调用setter,将单表数据映射到不同类?

PDO的PDO::FETCH_CLASS本身就支持直接给类的私有/受保护属性赋值——它通过底层机制绕过PHP的访问控制,无需显式调用setter方法。

关于你遇到的id属性未初始化问题

这通常是数据库列名与类属性名不匹配导致的:比如数据库列名为ID(大写),而类中属性是$id(小写),PDO默认对列名大小写敏感。可以通过两种方式解决:

  1. 在SQL语句中给列名指定别名,与类属性名保持一致:
$sql = "SELECT ID as id, name, price FROM $this->table";
  1. 配置PDO强制列名转为小写(或大写):
$this->conn->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);

映射到不同类

只需在fetchAll或fetch方法中传入目标类名即可:

// 映射到Book类
return $statement->fetchAll(PDO::FETCH_CLASS, 'Book');

如果目标类需要先完成属性赋值再调用构造方法,可以使用组合常量:

return $statement->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Book');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:10:00