在 PHP 会话中存储对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1442177/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:35:41  来源:igfitidea点击:

Storing objects in PHP session

phpsession

提问by Noah Goodrich

The PHP documentation says "You can't use references in session variables as there is no feasible way to restore a reference to another variable."

PHP 文档说“您不能在会话变量中使用引用,因为没有可行的方法来恢复对另一个变量的引用。”

Does this mean I can't have things like:

这是否意味着我不能有这样的事情:

session_start();
$user = new User;
$user->name = 'blah';
$_SESSION['user'] = $user;

I have tried to store a simple string and a User object in session, the string always persists between pages to pages, or after page refresh. However the User variable is lost in $_SESSION(becomes empty).

我试图在会话中存储一个简单的字符串和一个 User 对象,该字符串始终在页面之间或页面刷新后持续存在。然而,用户变量在 $_SESSION 中丢失(变空)。

any idea?

任何的想法?

Edit: I have confirmed that session_id is the same in all of these pages/subpages,before & after page refresh.

编辑:我已经确认 session_id 在所有这些页面/子页面中都是相同的,在页面刷新之前和之后。

Edit: Strangely, after I tried serialize and unserialize approach below, the serialized user object(or string) in session still still disappears!

编辑:奇怪的是,在我尝试了下面的序列化和反序列化方法后,会话中的序列化用户对象(或字符串)仍然消失了!

Edit: finally I figured out what the bug was, looks like somehow $_SESSION['user'] gets overwritten by some mysterious force, if I use any variable other than 'user', then everything's fine. PHP(at least 5.3 which is the version I'm using) does serialize and unserialize automatically when you put object in the $_SESSION.

编辑:最后我弄清楚了错误是什么,看起来 $_SESSION['user'] 以某种方式被某种神秘力量覆盖,如果我使用除 'user' 以外的任何变量,那么一切都很好。当您将对象放入 $_SESSION 时,PHP(至少 5.3 这是我使用的版本)会自动序列化和反序列化。

session_start();
$user = new User();
$user->name = 'blah'
$_SESSION['myuser'] = $user; 

回答by Noah Goodrich

You need to use the magic __sleep and __wakeup methodsfor PHP 5 Objects.

您需要为 PHP 5 对象使用神奇的 __sleep 和 __wakeup 方法

For example in the following code block:

例如在以下代码块中:

$obj = new Object();

$_SESSION['obj'] = serialize($obj);

$obj = unserialize($_SESSION['obj']);

__sleep is called by serialize(). A sleep method will return an array of the values from the object that you want to persist.

__sleep 由 serialize() 调用。sleep 方法将从您要保留的对象中返回一组值。

__wakeup is called by unserialize(). A wakeup method should take the unserialized values and initialize them in them in the object.

__wakeup 由 unserialize() 调用。唤醒方法应该采用未序列化的值并在对象中初始化它们。

回答by JPot

Your code example isn't using references as the documentation was referring to. This is what php means by references:

您的代码示例没有使用文档所指的引用。这就是 php 引用的意思

$var =& $GLOBALS["var"];

As to putting objects into the session, PHP canstore objects in $_SESSION. See http://example.preinheimer.com/sessobj.php.

至于将对象放入会话中,PHP可以将对象存储在$_SESSION. 请参阅http://example.preinheimer.com/sessobj.php

What you are seeing is a bugin the order of calls to __sleepand __destruct(__destructis being called before __sleep) and the session module fails to serialize the object at shutdown. This bug was opened on Sep 1, 2009.

您看到的是调用__sleep__destruct__destruct之前被调用__sleep)的顺序错误,并且会话模块无法在关闭时序列化对象。这个错误是在 2009 年 9 月 1 日打开的。

回答by jose segura

You were right saying you can not store references in sessions variables assigning an object in PHP 5 and above is doing just that assigning the reference not the obj

你说得对,你不能在会话变量中存储引用在 PHP 5 及更高版本中分配对象只是分配引用而不是 obj

That its why you would need to serialize the object (implementing also __sleep in the Class) and assigning the string to a session variable

这就是为什么您需要序列化对象(也在类中实现 __sleep )并将字符串分配给会话变量的原因

and deserializing it later (implementing also __wake in the Class) from the session variable later on.

并稍后从会话变量中反序列化它(也在类中实现 __wake )。

回答by Kirk Patrick Brown

For safe serialization and unserialization encode and decode with base64_encode() and base64_decode() respectively. Below I pass a serialized Object to a session and unserialize it on the other page to regain the variable to an object state.

为了安全的序列化和反序列化,分别使用 base64_encode() 和 base64_decode() 进行编码和解码。下面我将一个序列化的对象传递给一个会话,并在另一个页面上对其进行反序列化,以将变量恢复为对象状态。

Page 1

第 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;
?>

Page 2

第2页

<?php
session_start();
require  $_SERVER['DOCUMENT_ROOT'] .'/classes/RegistrationClass.php';
$reg_unserilizeObj = 
unserialize((base64_decode($_SESSION['regSession'])));
$reg_unserilizeObj->firstName;
?>

This article describes issues that may be faced by not doing so. issuses with php serialization/unserialization

本文介绍了不这样做可能会遇到的问题。 php 序列化/反序列化问题

回答by gbc

That's the expected behavior. Storing a reference to an object would only work if the memory location for the object didn't change. In a stateless protocol like HTTP, application state is not persisted between requests. The next request may be handled on another thread, process, or another server.

这是预期的行为。存储对对象的引用只有在对象的内存位置没有改变时才有效。在像 HTTP 这样的无状态协议中,应用程序状态不会在请求之间持久化。下一个请求可能会在另一个线程、进程或另一个服务器上处理。

Given the inherent stateless nature of a web application, holding a pointer to a memory location is useless. Therefore the object's state must be broken down into a storage format, saved or transmitted, and then reconstituted when needed. This process is known as Serialization.

鉴于 Web 应用程序固有的无状态特性,持有指向内存位置的指针是没有用的。因此,对象的状态必须分解为存储格式,保存或传输,然后在需要时重新构建。此过程称为序列化

You can choose to serialize the entire object into session (which maybe dangerous depending on the depth of your object graph, since your object may hold references to other objects and those would need to be serialized as well), or if the object can be reconstituted by querying the database on the next request you may just stash an ID in the session.

您可以选择将整个对象序列化到会话中(这可能很危险,具体取决于您的对象图的深度,因为您的对象可能持有对其他对象的引用,而这些对象也需要序列化),或者是否可以重新构建对象通过在下一个请求中查询数据库,您可以在会话中存储一个 ID。

[EDIT]

[编辑]

JPot pointed out that objects are automatically serialized to $_SESSION, so explicit serialization isn't necessary. I'll leave the answer for posterity, but obviously it doesn't help your problem.

JPot 指出对象会自动序列化为 $_SESSION,因此不需要显式序列化。我会把答案留给后代,但显然它对你的问题没有帮助。