0

0

对象克隆怎么做_PHP __clone魔术方法使用【详解】

星夢妙者

星夢妙者

发布时间:2026-03-11 21:00:55

|

577人浏览过

|

来源于php中文网

原创

__clone 方法仅在显式使用 clone 关键字时调用,不用于赋值、传参或序列化;它默认浅拷贝,需手动处理对象属性、资源和闭包;与序列化行为不同,不触发 __wakeup 或受 __sleep 控制。

对象克隆怎么做_php __clone魔术方法使用【详解】

__clone 方法什么时候会被调用

只有当你显式调用 clone 关键字时,__clone 才会触发——它不会在赋值、函数传参或 json_encode 时自动执行。很多人误以为“对象赋值就是深拷贝”,结果发现改副本也影响原对象,其实是根本没走 __clone

常见错误现象:Clone of non-object(克隆了 null 或资源类型)、Call to private __clone method(类里声明了 private __clone() 但没删掉)。

  • 必须配合 clone $obj 使用,单独定义 __clone 没任何效果
  • 如果父类有 private __clone(),子类即使重写也无法调用,得确保可访问性是 public
  • PHP 8.2+ 对内部类(如 SplFixedArray)克隆行为更严格,部分会直接报 Cannot clone object

深拷贝要手动处理引用属性

__clone 默认只做浅拷贝:对象属性里的标量和数组值会被复制,但对象、资源、闭包这些引用类型仍指向同一内存地址。你看到“副本改了,原对象也变了”,大概率是忘了克隆嵌套对象。

使用场景:需要独立副本的配置对象、DTO、带缓存属性的实体(比如 $this->cacheArrayObject)。

立即学习PHP免费学习笔记(深入)”;

  • 所有对象类型的属性都得显式 clone $this->prop,否则仍是引用
  • 资源(如 fopen 返回的句柄)不能克隆,需在 __clone 中重新打开或置为 null
  • 闭包无法克隆,会抛 __clone method called on closure,建议提前解构或改用可序列化结构

示例:

What-the-Diff
What-the-Diff

检查请求差异,自动生成更改描述

下载
class Config {
    public $data;
    public $cache;

    public function __clone() {
        $this->data = clone $this->data; // 假设 $data 是另一个对象
        $this->cache = null;            // 资源/缓存不继承,重置
    }
}

__clone 和序列化行为不一致

别指望 __cloneserialize/unserialize 效果一样。前者只复制当前对象状态,后者会重建整个对象图,且绕过构造函数;而 __clone 不触发 __wakeup,也不受 $allowed_classes 限制。

性能影响:克隆比反序列化快得多,尤其对大对象;但若依赖外部状态(如数据库连接),__clone 不会自动断开,容易引发并发问题。

  • unserialize() 会调用 __wakeupclone 完全不碰它
  • 如果类里用了 __sleep 控制序列化字段,__clone 无视这个逻辑,所有属性都参与克隆
  • 某些 ORM 实体(如 Doctrine Proxy)禁用克隆,直接抛异常,得先判断 is_object($obj) && method_exists($obj, '__clone')

替代方案比硬写 __clone 更可靠

不是所有对象都适合靠 __clone 实现深拷贝。比如含循环引用、动态生成属性、或依赖运行时上下文的对象,手写 __clone 很容易漏掉边角情况。

推荐优先考虑:json_decode(json_encode($obj), true)(仅限纯数据)、自定义 toCopy() 方法、或用 ReflectionClass 遍历属性做可控克隆。

  • json_encode/decode 会丢掉方法、私有属性、资源、对象类型信息,适合 DTO 场景
  • ReflectionClass 可跳过不可见属性,也能跳过静态/常量,但要注意 PHP 8.1+ 的只读属性(readonly)不能被反射修改
  • 第三方库如 myclabs/deep-copy 内部也是靠反射 + 白名单,但它能处理循环引用和特殊类型

真正难的不是写 __clone,而是判断哪些属性该克隆、哪些该重置、哪些根本不能碰——这得看具体业务逻辑,没法一劳永逸。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1089

2024.03.01

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1566

2023.10.24

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1566

2023.10.24

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1566

2023.10.24

go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

151

2025.07.29

go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

151

2025.07.29

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

384

2023.06.29

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.3万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号