给出一些背景;在添加Serializable接口之前,此过程正在运行。 TestAction2
在反序列化后没有保留对自身的引用;我尝试将Serializable
添加到Action
类并告诉它序列化$parent
,但仍然没有区别。尽管如此,它正确地将$method
字段反序列化。
类Action
在引用它($parent
)的类上进行序列化时序列化class B
字段中的引用,但在引用自身时不序列化A
。在类B
或Action
而不是class A implements Serializable {
private static $label;
public function serialize() {
return serialize(self::$label);
}
public function unserialize($serialized) {
self::$label = unserialize($serialized);
}
}
class B extends A {
private $actions;
public function serialize() {
return serialize([
'actions' => $this->actions,
'parent' => parent::serialize()]);
}
public function unserialize($serialized) {
$data = unserialize($serialized);
$this->actions = $data['actions'];
parent::unserialize($data['parent']);
}
public function addAction($anAction) {
$this->actions[] = $anAction;
}
public function process() {
$this->addAction(new TestAction1($this, 'test1')); // WORKS FINE
$this->addAction(new TestAction2($this, 'test2')); // WORKS NOT!
}
}
class Action {
private $parent;
private $method;
public function __construct($cParent, $sMethod) {
$this->parent = $cParent;
}
}
class TestAction1 extends Action {
public function __construct($cParent, $sMethod) {
parent::__construct($cParent, $sMethod);
}
}
class TestAction2 extends Action {
private $maybeNeedLater;
public function __construct($cParent, $sMethod) {
$this->maybeNeedLater = $cParent;
parent::__construct($this, $sMethod); // pass $this instead
}
}
$testThis = new B();
$testThis->process();
$serialized = serialize($testThis);
$testThis = unserialize($serialized);
类本身上发生序列化的事情。
Action
TestAction2
类$parent
在$actions
$testThis
字段中将显示空((()(
字段
答案 0 :(得分:1)
你的两个不同的Action类有点红鲱鱼,因为它们不是问题所在。 Test2恰好使用$ testThis以外的引用;许多其他参考也是错误的。
真正的问题是A / B类中的序列化顺序与反序列化的顺序不同。在序列化期间,PHP使用r(或R)和数字编码引用(r和R在许多方面是不同的,但差异只会分散计数问题)。在你的例子中,$ needThis可以用r:1;,A :: label用r:2;引用,actions数组用r:3;等等。 $ this对TestAction2对象的引用是r:8; (当你回复$ serialized时,你会看到这个。)
当你在unserialize函数中调用unserialize时,没有A :: label(还)。因为所有大于1的数字都会被一个数字关闭。 R:8;现在指向maybeNeedLater中的任何内容。
现在事情有点复杂,因为PHP通常不会创建这样的字符串。在PHP5中,它似乎创建了一些打印为NULL的错误。在PHP7中,parent实际上是对$ needThis的引用。
幸运的是,有几种简单的方法可以解决这个问题:
选项1:
使用不同的格式对父类进行编码:
class A implements Serializable {
private static $label;
public function serialize() {
return json_encode(self::$label);
}
public function unserialize($serialized) {
self::$label = json_decode($serialized);
}
}
选项2:
在子类中使用双序列化并确保订单适合:
class B extends A {
private $actions;
public function serialize() {
return json_encode([
'actions' => serialize($this->actions),
'parent' => parent::serialize()]);
}
public function unserialize($serialized) {
$data = json_decode($serialized, true);
$this->actions = unserialize($data['actions']);
parent::unserialize($data['parent']);
}
...