1

我正在构建一些常见的类对象,这些对象将被常规地隐藏在 $_SESSION 对象中。我了解到,在将对象添加到会话时,有时可以在不序列化的情况下添加它,但它不可靠,所以我先序列化并且它每次都有效。

我发现以下内容非常乏味/重复和笨重......就像我必须从会话中检查对象做一些工作然后记得以正确的方式检查它。有没有更好/更有创意的方式也有效且可重复使用。帮助php专家

// Painful Code
$tmpObj = new clsSession;  // Class setup for intellisense to work.
$tmpObj = unserialize($_SESSION['objSession']);  // I assign so i can get intellisense as well.  
$tmpObj //... do some work make some changes some other logic could be lengthy... 
// and then i have to remember to do the following
$_SESSION['objSession'] = serialize($tmpObj);
unset $tmpObj;

/* or better */

$tmpObj = $_SESSION['objSession'];
$tmpObj = unserialize($tmpObj);
$tmpObj //... do some work make some changes some other logic
//and then i have to remember to do the following
$_SESSION['objSession'] = serialize($tmpObj);
unset $tmpObj;
4

4 回答 4

0

在被序列化的对象中使用__sleep魔术方法。这只是返回请求之间所需的属性数组,并允许 SESSION 中的自动序列化对象正常工作。

例如

public function __sleep() {
    return array('these', 'are', 'property', 'identifiers');
}
于 2013-01-17T16:50:57.143 回答
0

您可以将对象直接存储到会话中,而无需先对其进行序列化。这是因为在保存会话时会自动进行序列化。只要确保您正在自动加载类定义。如果没有,您将必须在您希望使用存储的会话对象的每个页面上包含类定义。

于 2013-01-17T16:52:32.877 回答
0

除非我遗漏了什么,否则您所做的就是序列化两次:

<?php

class Foo{
    public $id;
}

$f = new Foo;
$f->id = 33;

var_dump( serialize($f) ); // Standard storage
var_dump( serialize(serialize($f)) ); // Yours

我能发现的唯一区别是标准的自动反序列化发生在会话加载(on session_start())上,这通常发生在早期阶段,并且您可能还没有加载类定义。使用您的代码,首先读取会话并在您unserialize()手动调用时重新组合对象。

我建议您查看您的include_once()指令并确保在 session_start() 发生之前加载所有必需的类定义。

这是一个非常强制的测试用例:

<?php

session_start();
if( empty($_SESSION) ){
    require_once('./foo.php');

    $f = new Foo;
    $f->id = 33;

    $_SESSION['f'] = $f;
    // object(Foo)#1 (1) { ["id"]=> int(33) } 
}else{
    $f = $_SESSION['f'];
    // object(__PHP_Incomplete_Class)#1 (2) { ["__PHP_Incomplete_Class_Name"]=> string(3) "Foo" ["id"]=> int(33) } 
}
var_dump($f);
于 2013-01-17T16:59:21.663 回答
0

蒂姆,谢谢你的意见。几年前,我遇到了对象和会话的稳定性问题;序列化和非序列化。会话反序列化期间缺少类定义很常见。如果类定义未定义,PHP 会创建类 __PHP_Incomplete_Class 的不完整对象。这个退化的对象错过了每一个方法。为避免此错误,必须在开始会话之前包含每个类定义。因此,如果您在开始会话之前实现自动加载器,您将不会遇到任何问题。该解决方案在过去 6 年多的时间里运行良好。

于 2013-01-18T14:05:38.013 回答