PHP 8.3中对象转数组不包含只读属性,需显式实现jsonSerialize();public/protected/private readonly属性均受作用域限制,fileinfo扩展必须启用以防序列化静默失败。

PHP 8.3 中,对象转数组(如通过 (array) 强制转换、get_object_vars() 或自定义序列化逻辑)在处理继承类的只读属性(readonly)时,行为与之前版本有关键差异——**不是所有属性都会被包含,且私有属性的可见性规则更严格**。兼容的关键不在于“加个函数”,而在于理解 PHP 8.3 的底层规则并主动适配。
只读属性默认不参与 (array) 转换
PHP 8.3 中,(array)$obj 和 get_object_vars($obj) 仅返回当前作用域下可访问的**非只读、非动态**属性。父类的 public readonly 属性虽可读,但不会出现在转换结果中;protected readonly 更是完全不可见。
- 若需导出只读属性,必须显式定义
jsonSerialize()或__toArray()方法 - 不要依赖魔术方法
__get()或__isset()来“补全”只读属性——它们不触发数组转换 - 示例:父类有
public readonly string $id;,子类调用(array)$child不会包含$id
继承链中属性可见性决定是否导出
属性能否被转成数组,取决于它在当前对象实例中的实际可见性,而非声明位置:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
-
public readonly:子类中可直接访问,但(array)仍不包含——需手动映射 -
protected readonly:子类可访问,但get_object_vars()在子类方法内调用时才可见;在父类方法中调用则不可见 -
private readonly:仅在声明它的类内部可见,子类无法访问,自然也不会导出
推荐兼容写法:统一用 jsonSerialize() 控制输出
绕过语言限制最稳妥的方式,是放弃依赖隐式转换,改用显式序列化接口:
- 在基类中定义
public function jsonSerialize(): array,显式列出所有需导出的只读属性 - 子类重写该方法时,调用
parent::jsonSerialize()并合并自有属性 - 避免使用
get_object_vars($this),改用array_merge()手动拼接 - 若需保持向后兼容,可在构造函数中缓存只读属性值到普通
public数组字段(仅作临时过渡)
注意 fileinfo 扩展对序列化的影响
虽然不直接影响数组转换,但 PHP 8.3 要求 fileinfo 必须启用,否则某些资源类(如 AssetBundle)在尝试序列化路径信息时会静默失败。运行 php -m | grep fileinfo 确认已加载,未启用会导致部分继承类的元数据丢失。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










