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,提问作者Григорий
相关产品推荐
相关产品推荐

