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默认对列名大小写敏感。可以通过两种方式解决:
- 在SQL语句中给列名指定别名,与类属性名保持一致:
$sql = "SELECT ID as id, name, price FROM $this->table";
- 配置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
相关产品推荐
相关产品推荐

