PHP是否序列化对象方法?

4
PHP参考手册称,在序列化对象时,方法不会被保存。(见http://www.php.net/manual/en/language.oop5.serialization.php第1段)。
然而,手册中给出的第一个示例显示了一个方法被序列化,然后被反序列化并使用。
这不是矛盾吗?我错过了什么吗?
2个回答

11

我必须说,我不知道在第一个例子中哪个方法被序列化了。当进行序列化时,只有类名和属性被序列化,没有方法被序列化。如果查看序列化数据,您可以看到这一点。

$ser = serialize($object);
var_dump($ser);

你会发现,这里没有提到任何方法。但是,如果你反序列化一个对象,它将通过类名重新创建。换句话说:你将得到一个新的对象,但具有之前序列化的值。

通常情况下,这并不像听起来那么重要,因为通常序列化/反序列化后的对象应该表现相同。

// serialize 
class A {
  public $a = null;
  public function test () {
    echo "Hello";
  }
}
$a = new A;
echo $a->test(); // "Hello"
$x = serialize($a);

// unserialize (somewhere else)
class A {
  public $a = null;
  public function test () {
    echo "World";
  }
}
$a = unserialize($x);
echo $a->test(); // "World"

这里的序列化器使用了一个“错误”的类,输出结果与预期不同。只要确保没有类名冲突,通常就无需考虑它。


非常感谢KingCrunch,您的解释真是太棒了。在阅读参考手册时,我做出了一些错误的假设。不过您的解释让问题变得十分清晰易懂。 - DatsunBing

2
该对象所属的类不是序列化的,但是该对象所属的类是序列化的:

对象中的方法不会被保存,只会保存类的名称。

因此,当您反序列化时,您会得到同一类的实例,因此您可以在未序列化的实例上调用该方法,因为该方法是类定义的一部分,而不是对象本身的成员。当然,这假设您在反序列化时具有完全相同的类定义:

为了能够反序列化()一个对象,该对象的类需要被定义。


这不是一个全新的实例。只是在对象序列化时返回该对象的阶段。 - Shakti Singh
@Shakti:这是一个新实例。你说得对,它重建了对象的预序列化状态,但是它是在一个新实例的基础上进行的。因为(例如)你可以从/向文件读取/写入序列化对象,所以没有办法在不同的调用之间保留实例。(($a === unserialize(serialize($a))) === false) - KingCrunch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接