PHP8.3的只读属性深拷贝怎么实现

落杰酱_3848

落杰酱_3848

2026-09-26

204人浏览

原创

php 8.3 的 readonly 属性在 clone 时保持只读,深拷贝必须通过静态工厂方法手动重建对象并递归处理嵌套只读实例,反射强制写入属未定义行为且不可靠。

php8.3的只读属性深拷贝怎么实现

PHP 8.3 只读属性不能被 clone 修改,深拷贝必须绕过只读限制

PHP 8.3 的 readonly 属性在对象克隆时仍保持只读语义——clone 不会复制出可写副本,而是直接复用原属性引用(尤其对嵌套对象/数组)。这意味着标准 clone 关键字无法实现真正“可修改的深拷贝”,你拿到的仍是带只读约束的对象实例。

手动重建对象:唯一安全的深拷贝方式

必须显式构造新实例,并逐个赋值属性。PHP 不允许在构造后写入 readonly 属性,所以所有数据必须在 __construct() 中注入。常见错误是试图在 __clone() 里赋值,这会直接报 Fatal error: Cannot modify readonly property。

  • 只读类应设计为“不可变即构造完成”,因此深拷贝逻辑应封装在静态工厂方法中,如 from() 或 withChanged(...)
  • 对嵌套的 readonly 对象,需递归调用其对应工厂方法,不能用 unserialize(serialize($obj)) —— 序列化会保留只读状态,反序列化后仍是只读
  • 若属性是数组且含只读对象,需用 array_map() 逐个转换,而非 array_replace_recursive()(后者不触发构造逻辑)
// 示例:从现有只读对象创建可修改副本
class Config
{
    public function __construct(
        public readonly string $host,
        public readonly int $port,
        public readonly array $features,
    ) {}

    public static function deepClone(Config $original): self
    {
        return new self(
            $original->host,
            $original->port,
            array_map(fn($f) => $f instanceof Feature ? Feature::deepClone($f) : $f, $original->features),
        );
    }
}

用 ReflectionProperty 强制写入?别试

虽然 PHP 8.3 允许通过反射临时解除只读($prop->setAccessible(true)),但这是危险且不可靠的操作:

btpanel phpsite 宝塔面板PHP网站
btpanel phpsite 宝塔面板PHP网站

宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理

下载
  • 仅对当前运行时有效,无法改变类型系统对属性的只读判定
  • 后续任何对该属性的写操作(包括 json_encode()、var_dump() 内部调用)都可能触发只读检查并崩溃
  • PHP 官方明确将此列为未定义行为(UB),8.4 可能彻底禁止
  • 即使成功,也无法解决嵌套只读对象的递归问题——你得对每一层都做反射,代码脆弱且难维护

第三方库如 spatie/data-transfer-object 在 PHP 8.3 下不适用

这类库依赖运行时属性写入或魔术方法,与 readonly 语义冲突。它们在 PHP 8.3+ 中要么抛出异常,要么静默失败(如跳过只读属性导致数据丢失)。真正可用的方案只有两类:

  • 纯手工工厂方法(推荐,可控、类型安全、无额外依赖)
  • 基于 AST 的代码生成工具(如 phpstan/phpstan 插件或自定义 CodeGenerator),在编译期生成 deepClone() 方法,但开发成本高

最常被忽略的一点:只读属性的“深拷贝”本质上是个语义矛盾——只读意味着你不该改它;所谓拷贝,其实是创建一个新不可变对象。别试图绕过只读,而是接受它,并把变化逻辑移到构造阶段。

php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php php8

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
编程语言有哪些
编程语言有哪些

编程语言有C语言、C++语言、Java语言、Python语言、JavaScript语言、Ruby语言、Go语言等。本专题为大家提供编程语言相关的各种文章、以及下载和课程。

2023.08.11

972

5

html转换txt文本格式方法
html转换txt文本格式方法

html通过使用在线工具、离线工具和编程语言来转txt。更多关于html转换txt文本格式方法详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.01

3095

8

c语言是什么编程语言
c语言是什么编程语言

c语言作为一种通用、结构化的编程语言,自诞生以来广泛应用于计算机领域。其基本特性包括结构化编程、过程式编程、底层访问能力、高效性能和跨平台性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

660

5

如何挑选适合初学者的编程语言
如何挑选适合初学者的编程语言

编程语言选择至关重要,它直接影响学习效率和职业发展。初学者选择易于入门且应用广泛的语言,能为未来的深造和职业规划奠定基础。选择不当可能导致学习曲线陡峭、应用范围狭窄、就业机会有限,甚至难以拓展其他领域。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2025.01.24

382

4

编程语言排行榜2025
编程语言排行榜2025

本专题文章深入分析2025年最新的编程语言流行度排名,基于TIOBE指数等权威数据,揭示Python、C++、Java等主流语言的最新动态与市场份额变化。通过对比各语言的优缺点、应用场景及就业前景,为开发者提供选择学习方向的实用参考,同时展望编程语言在人工智能、大数据和云计算等前沿技术中的未来发展。想了解更多详细内容,请阅读专题下面的文章。

2025.07.29

4047

27

java基础知识学习
java基础知识学习

本专题文章旨在为Java语言初学者提供系统化的学习路径,涵盖Java编程的核心基础知识、实用代码示例及全面的知识点总结。本专题适合零基础学习者及希望巩固Java基础的开发者,通过理论与实践结合,快速入门并迈向进阶开发。

2025.08.01

3904

26

2026 年编程语言排行榜与趋势解读
2026 年编程语言排行榜与趋势解读

本专题整合了编程语言排行榜合集,阅读专题下面的文章了解更多详细内容。

2026.05.29

18535

17

零基础编程语言选择与学习路线
零基础编程语言选择与学习路线

面向编程零基础用户与转行人群,系统分析不同编程语言的学习曲线、适用场景与就业前景,涵盖 Python(数据分析/AI/自动化/爬虫)、JavaScript/TypeScript(前端/全栈/小程序)、Java(企业后端/Android/大数据)、Go(云原生/微服务/DevOps)、C/C++(系统底层/嵌入式/游戏引擎)的定位对比与人群匹配建议、各语言从入门到实战的分阶段学习路线图、优质学习资源推荐(官方文档/在线课程/开源项目)、自

2026.05.29

604

20

php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2023.09.01

9344

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
墨刀帮助中心
墨刀帮助中心

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习