尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

TypePHP [With]不可变更新模式:clone-then-update的C风格实践

TypePHP [With]不可变更新模式:clone-then-update的C风格实践 TypePHP #[With]不可变更新模式clone-then-update的C#风格实践【免费下载链接】typephpCompile PHP to Native Binaries项目地址: https://gitcode.com/GitHub_Trending/ty/typephpTypePHP 是一款将 PHP 编译为原生可执行文件的 AOT 编译器其#[With]编译期属性可以一键生成 C# 风格的不可变更新方法克隆对象、修改副本并返回副本让更新不再触碰原对象实现零样板代码的 clone-then-update 实践。上图即为纯 PHP 源码编译运行的原生程序画面——#[With]生成的方法与手写代码一样在编译期直接落地为原生机器码不产生任何反射或分发开销。为什么需要不可变更新在业务代码里我们经常想基于现有对象改一个字段$config new AppConfig([timeout 30]); $prod new AppConfig([timeout 300]); // 复制粘贴重复写一遍全部字段传统的复制粘贴写法有两个痛点冗余字段越多重复构造越容易漏字段、错字段易错忘记带过某个字段时新对象悄悄变成默认值bug 很难排查。C# 的record类型用with { ... }表达式优雅解决了这个问题。TypePHP 则把同样的思想带进 PHP 世界——只靠一行属性声明。一行声明自动生成 with 方法 ✨给属性加上#[With]属性TypePHP 在 class lowering 阶段会自动生成一个withXxx()方法属性声明 src/polyfills.php 中的With就是一个空的编译期标记类final class User { #[With] public int $id; #[With] public string $name guest; } $user new User(); $user-id 7; $user-name Alice; $copy $user-withId(8); // 自动生成的方法 // $user 不变id7 // $copy 是副本id8name 保持 Alice生成的方法签名是public function withName(T $name): static其内部逻辑正是clone-then-update 三步走生成逻辑见 src/Transform/PropertyMethodLowering.php克隆——clone $this拿到一个深层次的独立副本更新—— 只修改副本上被 with 的那个属性返回—— 返回新副本原对象保持原样。哪些属性能用#[With]#[With]的目标与#[Setter]一致可变实例属性包括构造器提升属性。以下情况会被编译期直接拒绝场景是否可用说明普通实例属性✅#[With] public int $value;构造器提升属性✅public function __construct(#[With] private int $value)readonly属性❌只读属性无法在副本上更新见 phpunit/code/with-readonly-property.php带 property hook 的属性❌hook 会改变读写语义见 phpunit/code/with-hook-property.phpstatic 属性❌#[With]只作用于实例状态此外如果类中已显式声明同名withXxx()方法或生成的方法名冲突、覆盖继承而来的final方法编译期也会直接报错参考 phpunit/code/generated-method-final-parent-conflict.php避免运行期歧义。与 C#with表达的异同 对比点C# recordwithTypePHP#[With]更新方式表达式级一次可改多个字段方法级一个方法改一个字段链式调用可以可以$u-withId(8)-withName(Bob)类型安全强参数类型继承自属性声明类型运行时开销装箱/反射旧版本零编译为原生调用C# 的with更像改完就扔的表达式TypePHP 的方式更贴近 PHP 的方法调用习惯且每个withXxx()都是强类型的独立方法可以被类型系统完整推导。需要同时更新多个字段时链式调用即可$final $user-withId(8)-withName(Bob);如果你还想让改这件事在编译期就被静态拦截可以配合 TypePHP 的#[Immutable]只读契约使用——它同样零运行时开销相关设计见 docs/en/IMMUTABLE.md。另外 TypePHP 还支持 PHP 8.5 的clone($obj, [...])语法做一次性多字段更新参考 phpunit/code/clone-with-codegen.php。什么时候该用#[With]配置 / 参数对象需要频繁派生变体的场景函数式风格代码希望数据流向清晰、原对象不被中途污染减少样板属性一多手写的clone 赋值方法会非常啰嗦#[With]一行顶一段。完整的编译期属性#[Getter]、#[Setter]、#[With]、#[Constructor]、#[Printer]、#[Arrayable]说明可以参考 README-CN.md 中的编译期 Attribute 与代码生成章节README-CN.md#L368-L417。小结 #[With]用 C# 式的 clone-then-update 思想把 PHP 中繁琐的对象浅变体代码压缩成一行属性声明编译期生成强类型withXxx()方法克隆、更新、返回一步到位零运行时开销且冲突与语义错误都会在编译期暴露。对追求不可变语义又想要原生性能的团队来说这是 TypePHP 编译期代码生成能力中非常实用的一枚瑞士军刀。【免费下载链接】typephpCompile PHP to Native Binaries项目地址: https://gitcode.com/GitHub_Trending/ty/typephp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表