PHP文档说“你不能在会话变量中使用引用,因为没有可行的方法来恢复对另一个变量的引用。”
这是否意味着我不能拥有以下内容:
session_start();
$user = new User;
$user->name = 'blah';
$_SESSION['user'] = $user;
我试图在会话中存储一个简单的字符串和一个User对象,该字符串始终在页面之间或页面刷新之后保持不变。但是,$ _SESSION中的User变量丢失(变为空)。
任何想法?
编辑: 我已经确认session_id在所有这些页面/子页面中都是相同的,之前和之后页面刷新后。
编辑: 奇怪的是,在我尝试下面的序列化和反序列化方法后,会话中的序列化用户对象(或字符串)仍然消失!
编辑: 最后我弄明白了这个bug是什么,看起来好像以某种神秘力量覆盖$ _SESSION ['user'],如果我使用除'user'以外的任何变量,那么一切都很好。当你将对象放在$ _SESSION中时,PHP(至少5.3这是我正在使用的版本)会自动序列化和反序列化。
session_start();
$user = new User();
$user->name = 'blah'
$_SESSION['myuser'] = $user;
答案 0 :(得分:50)
您需要将magic __sleep and __wakeup methods用于PHP 5对象。
例如,在以下代码块中:
$obj = new Object();
$_SESSION['obj'] = serialize($obj);
$obj = unserialize($_SESSION['obj']);
__ sleep由serialize()调用。 sleep方法将返回您要保留的对象的值数组。
__ wakeup由unserialize()调用。唤醒方法应该采用未序列化的值并在对象中将它们初始化。
答案 1 :(得分:2)
您的代码示例未使用文档所指的引用。 This is what php means by references:
$var =& $GLOBALS["var"];
关于将对象放入会话,PHP 可以在$_SESSION
中存储对象。请参阅http://example.preinheimer.com/sessobj.php。
What you are seeing is a bug按照__sleep
和__destruct
(__destruct
之前调用__sleep
的调用顺序,会话模块无法序列化对象在关机。这个bug于2009年9月1日开通。
答案 2 :(得分:1)
你是对的,说你不能在会话变量中存储引用 在PHP 5及更高版本中分配一个对象只是指定引用而不是obj
这就是为什么你需要序列化对象(在类中实现__sleep)并将字符串赋值给会话变量
稍后在会话变量中反序列化它(在类中也实现__wake)。
答案 3 :(得分:1)
分别使用base64_encode()和base64_decode()进行安全序列化和反序列化编码和解码。下面我将一个序列化的对象传递给一个会话,并在另一个页面上反序列化它以将变量重新恢复为一个对象状态。
第1页
<?php
require $_SERVER['DOCUMENT_ROOT'] .'/classes/RegistrationClass.php';
$registrationData= new RegistrationClass();
$registrationData->setUserRegData();
$reg_serlizer = base64_encode(serialize($registrationData)); //serilize the object to create a string representation
$_SESSION['regSession'] = $reg_serlizer;
?>
第2页
<?php
session_start();
require $_SERVER['DOCUMENT_ROOT'] .'/classes/RegistrationClass.php';
$reg_unserilizeObj =
unserialize((base64_decode($_SESSION['regSession'])));
$reg_unserilizeObj->firstName;
?>
本文介绍了不这样做可能会遇到的问题。 issuses with php serialization/unserialization
答案 4 :(得分:0)
这是预期的行为。仅当对象的内存位置未更改时,才存储对对象的引用。在像HTTP这样的无状态协议中,请求之间不会持久保存应用程序状态。可以在另一个线程,进程或另一个服务器上处理下一个请求。
鉴于Web应用程序固有的无状态特性,保持指向内存位置的指针是没用的。因此,必须将对象的状态分解为存储格式,保存或传输,然后在需要时重新构建。此过程称为Serialization。
您可以选择将整个对象序列化为会话(这可能很危险,具体取决于对象图的深度,因为您的对象可能包含对其他对象的引用,并且那些也需要序列化),或者如果对象可以通过在下一个请求中查询数据库来重构,您可以在会话中存储ID。
[编辑]
JPot指出对象会自动序列化为$ _SESSION,因此不需要显式序列化。我会给后人留下答案,但显然这对你的问题没有帮助。