__clone 方法仅在显式使用 clone 关键字时被调用,赋值、传参或返回对象不会触发;若未定义则执行浅拷贝,定义后需手动复制属性,不可赋值 $this,继承时应调用 parent::__clone() 并重置业务唯一字段。

PHP __clone 方法什么时候会被调用
只有在你显式使用 clone 关键字复制对象时,__clone 才会被触发。它不会在赋值($b = $a)、函数传参或返回对象时自动运行——PHP 对象默认就是引用传递,这些场景根本不会产生新实例。
常见错误现象:__clone 完全没执行,结果发现你只是写了 $new = $old,以为这就算“克隆”了。
- 必须写
$new = clone $old;,否则__clone永远不会进 - 如果类没定义
__clone,PHP 会做浅拷贝(即只复制对象属性值,不递归克隆嵌套对象) - 一旦定义了
__clone,PHP 就不再自动处理属性复制,你得手动写$this->prop = $that->prop;或调用parent::__clone();
为什么不能直接在 __clone 里用 $this = $that
这是新手最常试也最常错的操作:$this = $that 在 __clone 里完全无效,甚至会报 Fatal error: Cannot re-assign $this。PHP 的 $this 是只读的当前对象引用,不能被覆盖。
正确做法是逐个重置属性。尤其要注意资源型、对象型、数组型属性是否需要深拷贝。
立即学习“PHP免费学习笔记(深入)”;
- 简单类型(
int、string、bool)可直接赋值:$this->id = $that->id; - 嵌套对象要显式
clone:$this->handler = clone $that->handler; - 资源(如
curl句柄、文件指针)无法克隆,必须重新初始化或设为null - 静态属性和常量不受
__clone影响,它们属于类,不属于实例
__clone 中漏掉 parent::__clone() 会怎样
如果你继承了一个父类,而父类自己实现了 __clone 来处理关键属性,但子类重写了它却忘了调用 parent::__clone(),那么父类那部分逻辑就彻底丢失了——比如数据库连接被关闭、缓存句柄未重置、内部计数器没归零。
这不是语法错误,而是静默失效。调试时很难定位,因为对象看起来“能用”,但某些状态已损坏。
- 只要父类有自定义
__clone,子类重写时第一行建议加parent::__clone(); - 如果父类没有
__clone,调用parent::__clone()会报Fatal error: Call to parent::__clone() when current class doesn't extend any class - 安全写法是先判断:
if (method_exists('parent', '__clone')) { parent::__clone(); }
克隆后 ID、时间戳、唯一标识等字段怎么处理
很多业务对象带自增 ID、创建时间、token 等一次性字段,克隆时若不重置,会导致两个对象拥有相同 ID,后续保存进数据库或校验时出问题。
这不是 __clone 的职责边界问题,而是业务逻辑必须介入的地方。PHP 不可能知道你的 $id 是主键还是普通编号。
- 数据库模型类克隆后应清空
$this->id和$this->created_at - 带 token 的会话对象,克隆后需生成新
$this->token = bin2hex(random_bytes(16)); - 避免在
__clone里做耗时操作(如查库、发 HTTP 请求),它应该轻量、确定、无副作用
__clone 不会替你猜,也猜不到。









