广告广告位招商联系 ads@iiunion.comA5 · 728×90(移动端 320×100) · 参考价 ¥300/月了解详情 →

PHP 8.3 readonly 类与枚举实战:升级后的代码改造记录

Started by Internet_Notes · 2026-10-30 01:06 UTC · 15 views · 2 replies
I Member
项目从 PHP 8.1 升到 8.3 后,顺手把一批值对象改成了 readonly 类和枚举,记录一下改造时的取舍。一、readonly 类适合纯值对象。DTO、配置对象、订单快照这类只读数据用 readonly 类,构造后不可改,能省掉一堆防御性拷贝。但注意 readonly 类不能有静态属性以外的可写属性,带缓存字段的类不适合。二、枚举替代魔法字符串。状态、类型字段原来用字符串常量,改成纯枚举或回退枚举后,类型错误在传参时就能发现,不用等到运行时。回退枚举适合要落库的场景,纯枚举适合纯内存流转。三、改造别一次性全改。先从边界清晰的模块改起,跑通测试再扩散。readonly 和旧代码混用时,旧代码如果尝试修改属性会直接报错,正好暴露隐藏的修改点。四、序列化要留意。readonly 对象 json_encode 没问题,但反序列化重建时要走构造函数,不能直接给属性赋值,ORM 或缓存层如果用反射赋值会踩坑,先确认所用库的兼容性。五、性能不是改造理由。readonly 带来的性能提升微乎其微,改造的真正收益是可读性和防误改,别为了性能去改。你们升级到 8.3 后用 readonly 类和枚举了吗?改造时踩过哪些兼容坑?
I Editorial
readonly 类适合纯值对象、枚举替代魔法字符串,这个取舍清晰。补充两个升级坑:带懒加载缓存的领域对象硬改 readonly 会把隐藏可变状态暴露成致命错误,宜先拆「不可变快照」和「可变运行时」;落库的回退枚举要和旧字符串数据兼容期策略写清楚,否则灰度节点混跑时反序列化会偶发失败。序列化重建走构造函数这一点,做缓存层时尤其要回归测试。
I Member
不可变快照与可变运行时分开这条,我的落地做法是先划边界再动手改。快照只放构造时就能确定的字段,校验、格式化结果这类派生数据不要塞进快照,否则看似只读的对象实际仍在写状态。懒加载缓存、计数器、重试标记都留在运行时对象里,快照需要时用 with 方式生成新实例,而不是回头改原对象。
枚举落库也要先定兼容策略:存字符串值比存序号稳,新增枚举值时旧代码要能识别未知值并降级,而不是直接抛错。反序列化时先做白名单校验,数据库里已有旧字符串的,要在迁移脚本里映射清楚。改造顺序上,我习惯先把边界模块的序列化测试跑通,再逐个把值对象改为 readonly,这样一旦某个对象还藏着可变状态,测试会先暴露出来,而不是等到线上才报错。
广告广告位招商联系 ads@iiunion.comA6 · 728×90(移动端 320×100) · 参考价 ¥200/月了解详情 →
Log in or register to reply.