如前所述,__sleep()
当您serialize()
是一个对象并__wakeup()
在您之后调用unserialize()
它。
序列化用于持久化对象:您将获得对象的表示形式,然后可以将其存储在$_SESSION
数据库、cookies 或您想要的任何其他地方。
资源价值
但是,serialize()
不能序列化(即转换为文本表示)资源类型的值。unserialize()
这就是为什么在ing之后所有这些值都会丢失的原因。
对象图
or members, and the member's members and the ... ad infinitum
另一个也许更重要的一点是,如果你序列化它,serialize()
它将遍历整个对象图。$obj
这在您需要时非常有用,但是如果您只需要对象的一部分并且某些链接对象是“特定于运行时的”并且在许多对象之间以及其他对象之间共享,那么您可能不希望这种行为。
PHP 正确处理循环图!含义:如果 $a (的成员)链接到 $b,并且 $b 链接到 $a 被正确处理,但无论有多深。
示例 - 会话特定(共享)对象
例如,一个$database
对象被 引用$obj->db
,但也被其他对象引用。您将希望$obj->db
成为相同的对象 - 在unserialize()
ing 之后 - 下一个会话中的所有其他对象都具有,而不是数据库对象的孤立实例。
在这种情况下,你会有这样的__sleep()
方法:
/**
/* DB instance will be replaced with the one from the current session once unserialized()
*/
public function __sleep() {
unset($this->db);
}
然后像这样恢复它:
public function __wakeup() {
$this->db = <acquire this session's db object>
}
另一种可能性是,该对象是需要注册的某些(全局)数据结构的一部分。您当然可以手动执行此操作:
$obj = unserialize($serialized_obj);
Thing::register($obj);
但是,如果它是需要在该注册表中的对象契约的一部分,那么将这个神奇的调用留给对象的用户并不是一个好主意。理想的解决方案是,如果对象关心它的职责,即在Thing
. 这就是__wakeup()
允许您对您的客户透明地做的事情(即他不再需要担心这种神奇的依赖)。
同样,如果合适,您可以使用__sleep()
“取消注册”对象。(对象在序列化时不会被销毁,但在您的上下文中可能有意义。)
闭包
最后但同样重要的是,闭包也不支持序列化。这意味着您将不得不重新创建所有附加的闭包__wakeup()
。