You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP:如何无需序列化恢复被引用覆盖的对象

无需序列化恢复被覆盖对象的方案

当然有,核心思路是保留原对象的引用,而非依赖序列化/反序列化。PHP中只要对象存在活跃引用,就不会被垃圾回收,我们可以直接让被覆盖的变量重新指向原对象。

具体实现代码

function modify(object &$obj): void {
    $obj = new \StdClass();
}

function back(object &$obj, object $originalObj): void {
    // 直接将变量重新指向原对象,无需序列化操作
    $obj = $originalObj;
}

$originObject = new \StdClass;
$originalReference = $originObject; // 保存原对象的引用,避免被GC回收

$objectIdBeforeModify = \spl_object_id($originObject);
\var_dump($objectIdBeforeModify); // 输出原对象ID,示例为1

modify($originObject); // 变量被强制指向新对象
$objectIdAfterModify = \spl_object_id($originObject);
\var_dump($objectIdAfterModify); // 输出新对象ID,示例为2

back($originObject, $originalReference);
$returnedObjectId = \spl_object_id($originObject);
\var_dump($returnedObjectId); // 输出原对象ID1,与初始状态一致

原理说明

  • 执行$originalReference = $originObject;时,相当于给原对象新增了一个引用,即便$originObject被修改指向新对象,原对象仍会保留在内存中。
  • back函数直接将变量重新赋值为原对象的引用,就能让变量回到最初指向的对象,全程不需要序列化,效率更高,还能规避序列化带来的潜在问题(比如对象包含不可序列化资源、魔术方法干扰等)。

如果想从源头避免对象被覆盖,还可以封装一个容器类,只允许修改对象属性,禁止替换整个对象:

class ObjectWrapper {
    public function __construct(private object $obj) {}

    // 仅提供修改属性的入口
    public function setProperty(string $name, mixed $value): void {
        $this->obj->$name = $value;
    }

    // 获取原对象
    public function getObject(): object {
        return $this->obj;
    }
}

// 使用示例
$wrapper = new ObjectWrapper(new \StdClass());
$wrapper->setProperty('test', 'demo'); // 只能通过容器修改属性,无法替换内部对象

内容的提问来源于stack exchange,提问作者Григорий

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:32:46