我可以将类实例存储在 $_SESSION 空间中吗?

Posted

技术标签:

【中文标题】我可以将类实例存储在 $_SESSION 空间中吗?【英文标题】:Can I store a class instance in a $_SESSION space? 【发布时间】:2011-10-28 08:04:30 【问题描述】:
 Class User

public $id;
public $username;
public $password;
public $email;
public $steam;
public $donator;
public $active;

public function __construct($username, $email, $password, $id, $active, $donator, $steam)
    $this->id = $id;
    $this->username = $username;
    $this->password = $password;
    $this->email = $email;
    $this->steam = $steam;
    $this->donator = $donator;
    $this->active = $active;

是我的课(简体)

以下是我的代码:

$_SESSION['loggedIn'] = $user;

$user 是 User 的类实例

现在这就是 print_r($_SESSION['loggedIn']) 向我展示的内容:

    __php_Incomplete_Class Object
(
    [__PHP_Incomplete_Class_Name] => User
    [id] => 22
    [username] => xxxx
    [password] => xxxx
    [email] => xxxx
    [steam] => 1234567
    [donator] => 0
    [active] => 1
)

其中 xxxx 是正确的值。

但是当我尝试从我的会话中检索数据时。像这样: "$_SESSION['loggedIn']->username" 它返回一个空值给我。

【问题讨论】:

"Storing A PHP Object In A Session Variable"、"PHP Session with an Incomplete Object"、"Problem with PHP Session Object" 的可能副本。 另见"PHP: Storing 'objects' inside the $_SESSION"、"Can I Store An Object In A Session?"。 我不会那样做的。例如,如果用户在另一台计算机上登录时使用另一台计算机更改他的电子邮件,您最终可能会得到旧数据。或者,如果您从数据库中删除用户,您的应用程序仍会认为该用户存在。相反,我会在会话中只存储用户 ID,并在处理来自用户的请求时从数据库中检索其余信息。 【参考方案1】:

$_SESSION 变量似乎只能存储数组、数字和字符串。

在您切换到新页面后,它们无法存储类对象。

【讨论】:

好的,那么我能做的是在会话中创建一个数组吗?并用从 do-login.php 检索到的某些值填充它? @Toby,是的,你可以这样做。 你有这个来源,或者这是一个错误的答案(来自其他答案)。 @BramVanroy 如果您阅读了其他答案(或至少是已接受的答案),它们只是将字符串存储到会话而不是对象 嗯,是的。一个序列化的对象,然后可以将其反序列化回“成为”一个对象,对吗?还是我错过了序列化和反序列化的重点。【参考方案2】:

您必须先将对象序列化为字符串:

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

和:

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

只需确保在反序列化对象之前首先定义类。

【讨论】:

PHP 将自动生成 serialize 和 unserialize 会话变量。这个答案有效的原因是关于确保在反序列化之前定义类的注释。 @outis 你能提供参考吗?您发布的两个链接已失效,但我正在寻找确认序列化确实是自动完成的参考。 @Bram:链接指向源代码;具体来说,ext/session/session.c。这是我知道的唯一参考(有相当多的 PHP 行为没有记录)。【参考方案3】:

在同一页面上,session 变量就像另一个变量,因此您可以随心所欲地使用它。这就是您可以在该页面上存储对象的原因。

稍后检索它实际上会显示它是否适合 session,但您的情况并非如此。

如果您确实需要保存该对象,可以尝试将其保存为序列化对象,并在检索后将其反序列化。这应该可行,尽管我不知道这是否是最好的解决方案/设计。像这样传递对象可能会被认为有点......反模式

【讨论】:

【参考方案4】:

您可以将对象存储在$_SESSION 中。 PHP 将为您序列化它们。只需确保在调用session_start 之前定义了类,或者它可以是autoloaded。存储在会话中的值具有“__PHP_Incomplete_Class_Name”类型的原因是在会话加载期间反序列化对象时未定义用户类(如object serialization 上的 PHP 手册页中所述)。

资源无法序列化。如果您曾经存储使用资源的对象,请实现 __sleep and __wakeup 以自定义序列化。 PHP 的序列化应该能够处理所有其他类型,即使它们包含循环引用。

【讨论】:

以上是关于我可以将类实例存储在 $_SESSION 空间中吗?的主要内容,如果未能解决你的问题,请参考以下文章

我可以将函数的输出参数存储到 unique_ptr 中吗?

使用 Qt 将类实例加载到单独的进程中

将类名存储在类变量中而不输入类名?

会话保存在哪里?

在实例化时将类转换为子类

无法将类实例传递给构造函数