PHP clone默认浅拷贝:标量和数组值被复制,对象、资源等引用类型仍共享内存地址;要实现深拷贝,必须在__clone()中手动克隆嵌套对象或用serialize/unserialize兜底。

clone 是 PHP 实现原型模式最直接、最底层的机制,但它默认只做浅拷贝。要真正落地原型模式,必须结合 __clone() 魔术方法 + 显式处理引用类型属性,否则克隆后修改子对象会污染原对象。
PHP 的 clone 默认行为就是浅拷贝
执行 $copy = clone $original; 时,PHP 会:
- 创建新对象实例
- 复制所有属性值:标量(int、string、bool)和数组是值拷贝;
- 对象类型属性复制的是引用(即内存地址),不是新对象
这意味着:$copy->obj 和 $original->obj 指向同一个实例。改一个,另一个跟着变。
用 __clone() 手动实现深拷贝
只要类中存在对象类型属性,就必须在 __clone() 里手动克隆它们。否则深拷贝不成立:
class User {
public string $name;
public Address $address;
<pre class="brush:php;toolbar:false;">public function __clone() {
// 必须显式克隆引用对象,否则还是浅拷贝
$this->address = clone $this->address;
}
}
- 没写
__clone()→ 沿用默认浅拷贝逻辑 - 写了但漏掉某个对象属性 → 该属性仍共享引用
- 对象属性本身没实现
__clone()→clone $this->address仍只是浅拷贝它内部的引用
用 serialize/unserialize 做“无脑”深拷贝
当对象结构复杂、嵌套深、或你不确定哪些属性要克隆时,可以绕过 __clone(),用序列化兜底:
function deepClone($object): object {
return unserialize(serialize($object));
}
- 优点:不用逐个处理属性,自动递归深拷贝所有层级
- 缺点:要求所有嵌套对象可序列化(不能含资源、闭包、部分 PDO 对象等)
- 性能开销比手动
clone大,频繁调用要注意 - 不触发
__clone(),所以类内自定义逻辑(如重置 ID、清空缓存)不会执行
原型模式真正的价值不在“复制”,而在“免初始化”
原型模式的核心优势不是语法糖,而是跳过构造函数和初始化逻辑:
-
new User($name, $addr)每次都执行__construct(),可能含 DB 查询、IO、计算 -
clone $prototype不调用__construct(),只做内存拷贝或序列化还原 - 所以原型对象应提前准备好“稳定状态”,比如已加载配置、预设默认值、连接池已就绪
最容易被忽略的一点:原型对象本身必须是**可复用的干净实例**。如果原型里存了临时状态(如请求上下文、单次 token),克隆出来照样带毒 —— 深拷贝解决不了设计问题,只解决引用污染。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











