PHP 5 - 序列化对象并存储它们的关系

标签 php caching serialization

我正在编写一个相当复杂的 PHP 应用程序,其中单个用户操作可以触发许多其他子系统中的更改,并且我正在考虑使用观察者模式。但是,我想知道是否必须重新创建所有涉及的对象。

是否可以在序列化对象时存储它们的关系?例如

$equipmentHandler = new EquipmentHandler();
$character = new Character();
$character->subscribeOnEquipmentChanged($equipmentHandler);

$_SESSION['character'] = serialize($character);
$_SESSION['subscriber'] = serialize($equipmentHandler);

反序列化后关系会保留吗?或者我是否必须将它们全部集中到一个对象中?

$cache['character'] = $character;
$cache['subscriber'] = $equipmentHandler;
$_SESSION['cache'] = serialize($cache);

如有任何建议,我们将不胜感激。

(PS。字符数据需要许多数据库请求来创建,我正在考虑通过写入缓存和数据库来存储它,但只能从缓存策略中读取,因此无论如何它都会被序列化)

最佳答案

关系将会保留,但会与你期望的不同。当您序列化两个引用同一个 EquipmentHandler 的 Character 实例时,您将获得此 EquipmentHandler 的两个单独的实例,而不是您期望的单个实例。正如本例所示:

<?php

echo "BEFORE SERIALIZE:\n";
class A { }
class B { }

$a = new A;
$b = new B;
$a -> b = $b;

$a2 = new A;
$a2 -> b = $b;

var_dump($a->b);
var_dump($a2->b);

echo "AFTER SERIALIZE:\n";
$a3 = unserialize(serialize($a));
$a4 = unserialize(serialize($a2));

var_dump($a3->b);
var_dump($a4->b);

其输出是:

BEFORE SERIALIZE:
object(B)#2 (0) {
}
object(B)#2 (0) {
}
AFTER SERIALIZE:
object(B)#5 (0) {
}
object(B)#7 (0) {
}

查找井号后面的数字。这是指 PHP 中的对象 ID。在序列化之前,$a->b 和 $a2->b 都引用对象 ID #2 的对象:同一个实例。但序列化后,它们引用对象 ID #5 和 #7:不同的实例。

这对您来说可能是问题,也可能不是问题。

要恢复与单个 B 对象的连接,您必须采取一些技巧。您可以在 A 中使用 __sleep() 处理程序将对 B 实例的实际引用扁平化为仅提及 B:“我有对 B 的引用”。然后使用 A 中提到的 B 实例来实现 __wakeup() 处理程序,以获取新 B 对象的单个实例。

顺便说一句。 PHP session 扩展已经自动序列化,无需您自己预序列化:)

关于PHP 5 - 序列化对象并存储它们的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1318175/

相关文章:

java - 当我可以将类文件复制到新的 JVM 时,为什么要在 java 中进行序列化?两者都执行相同的任务,对吗?

php - laravel 5.4 输入日期时出错

php - 如何在 .html 文件中包含 .php 或 .html 文件?

javascript - 初始化本地存储的正确方法?

iOS 使用 AFImageCache 缓存图像似乎不起作用

python - Django - 如何序列化继承

java - java Matlab 的可序列化性

php - 整洁的函数 parseString()、repairString()、cleanRepair() 之间有什么区别

c - CPU缓存对速度的影响

java - Memcached - 缓存必须与数据库同步的信息