编辑:问题是一个记录在案的PHP错误:https://bugs.php.net/bug.php?id=71617感谢找到一个@Danack
我只是将应用程序从PHPH 5.5迁移到PHP 7,并且在序列化对象时偶然发现了一些奇怪的行为。
我试图将其简化为一个最小,完整且可验证的示例,可以在http://sandbox.onlinephpfunctions.com/code/e926a7398119ea715531cafe4ce6a22c329e53b8
找到问题在于,如果某个类扩展ArrayObject,那么如果您serialize()
然后unserialize()
该对象,则所有私有属性似乎都会消失:
serialize()
object unserialize()
第4步的结果我尝试将其简化为一个最小,完整且可验证的示例,可以在http://sandbox.onlinephpfunctions.com/code/e926a7398119ea715531cafe4ce6a22c329e53b8找到,您可以使用不同的PHP版本测试代码。
<?php
class demoStdObject {
public $public = ''; protected $protected = ''; private $private = '';
public function getPublic() { return $this->public; }
public function getProtected() { return $this->protected; }
public function getPrivate() { return $this->private; }
public function setPublic($public) { $this->public = $public; }
public function setProtected($protected) { $this->protected = $protected; }
public function setPrivate($private) { $this->private = $private; }
}
class demoArrayObject extends ArrayObject {
public $public = ''; protected $protected = ''; private $private = '';
public function getPublic() { return $this->public; }
public function getProtected() { return $this->protected; }
public function getPrivate() { return $this->private; }
public function setPublic($public) { $this->public = $public; }
public function setProtected($protected) { $this->protected = $protected; }
public function setPrivate($private) { $this->private = $private; }
}
$arrayObject = new demoArrayObject();
$stdObject = new demoStdObject();
testSerialize($arrayObject);
echo str_repeat('-',30) . "\n";
testSerialize($stdObject);
function testSerialize($object) {
$object->setPublic('public');
$object->setProtected('protected');
$object->setPrivate('private');
$serialized = serialize($object);
$unserialized = unserialize($serialized);
echo get_class($object) . ":\n";
echo $unserialized->getPublic() . "\n";
echo $unserialized->getProtected() . "\n";
echo $unserialized->getPrivate() . "\n";
}
PHP 5.6的输出:
demoArrayObject:
public
protected
private
------------------------------
demoStdObject:
public
protected
private
PHP 7的输出:
demoArrayObject:
public
protected
------------------------------
demoStdObject:
public
protected
private
我找不到与serialize()
,unserialize()
或ArrayObject
课程相关的任何记录更改,因此我想知道发生了什么。这是一个错误吗?未记载的功能? ; - )
正如我们在项目中做了很多serialize()
/ unserialize()
一样,我确实需要确保PHP 7的行为与PHP 5.3+行为100%兼容。
问题:如何使PHP 7的行为类似PHP 5.3 + ??
答案 0 :(得分:2)
虽然这对于PHP的下一个版本是固定的,但是您的代码依赖于未记录的行为这一事实是一个错误,称为&#34; Programming by Coincidence&#34;。从精美的文章:
如何巧合编程
假设Fred有一个编程任务。 Fred在某些代码中键入,尝试它,它似乎工作。 Fred在更多代码中输入,尝试它,它似乎仍然有用。经过几周的编码,程序突然停止工作,经过几个小时的尝试修复后,他仍然不知道为什么。弗雷德可能会花费大量时间来追逐这段代码而无法修复它。无论他做什么,它似乎都无法正常工作。
实施意外
实现的意外事件只是因为这是当前编写代码的方式。您最终依赖于未记录的错误或边界条件。
在这种情况下,无法保证在扩展ArrayObject时,子类的值将被正确地反序列化。
使用组合而不是继承会更安全,或者在子方法上编写序列化/反序列化方法将允许您控制序列化/反序列化。或者,只是不使用序列化/反序列化而是使用您自己的界面也可以比“魔法”#34;更可预测。内部方法。