编程 PHP 8.4 升级笔记:property hooks 和 readonly 不能共存,E_STRICT 移除会改 CI 行为

2026-09-12 21:02:02

PHP 8.4 升级笔记:property hooks 和 readonly 不能共存,E_STRICT 移除会改 CI 行为

PHP 8.4 于 2024-11-21 发布,活跃支持到 2026-12-31,安全修复到 2028-12-31。下面是迁移时真正会踩到的不兼容点。

新特性,以及它们自带的坑

Property hooks 是 8.4 的头号特性:属性可以挂 get/set 逻辑,没有 backing store 时就是虚拟属性。几个坑:

  • 传给构造函数的值必须匹配声明类型,不管 hook 接受什么类型。
  • property hooks 与 readonly 属性不兼容,手册里明确写了这一点。
  • 获取引用或间接修改可能绕过 set hook。如果调用者经常修改数组元素,避免在这个属性上用 hook,尽量「替换整个数组」。

不对称可见性:可以设成 public 读、private(set) 写。可见性是 get-visibility,get visibility 不能比 set visibility 更严格。

新增数组函数array_findarray_find_keyarray_anyarray_all

#[Deprecated] attribute:用户态弃用标记,触发 E_USER_DEPRECATED,注意不是 E_DEPRECATED

新 DOM APIDom 命名空间,HTML5 标准兼容解析,Dom\HTMLDocument / Dom\XMLDocument;旧 DOM 类仍然保留。

PDO 驱动特定子类Pdo\MySqlPdo\PgsqlPdo\Sqlite 等。

Lazy objects:主要用于框架和基础设施层。

会表现为随机测试失败的变更

  • E_STRICT 被移除,E_STRICT 常量已弃用。遗留代码或配置里引用它,CI 行为就会跟着变。
  • JIT 配置默认值变了(OPcache 侧),从 tracing 改了默认值。
  • 扩展更严格:Date、Intl、PDO、Reflection、SPL、SQLite、XMLReader 的多个扩展类常量现在有类型。
  • 一些函数改为抛 ValueError,不再静默接受无效输入:round() 的无效 mode、str_getcsv() 分隔符长度不为 1 字节。round() 传无效 mode 现在抛 ValueError,之前会当成 PHP_ROUND_HALF_UP
  • SimpleXML 迭代行为变化,避免意外 rewind,此前可能导致无限循环。
  • 部分 PDO 属性按驱动表现为布尔而非整数。

这些属于「不早点在 8.4 下跑测试套件,就会表现为随机测试失败」的变更。

迁移顺序

  1. 先把 8.4 加到 CI 里跑测试套件,把警告和弃用当信号。
  2. 只在新代码里用 array_find / array_any / array_all
  3. 新 DTO 用不对称可见性。
  4. 明显能替代样板代码的地方加 property hooks。
  5. #[Deprecated] 做内部 API 清理。
  6. 新 DOM API 先在脚本或隔离模块里用。
  7. lazy objects 留给框架层。
复制全文 生成海报 PHP 版本升级 迁移

推荐文章

程序员茄子在线接单