PHP OOP会话对象 - 序列化UnSerialize - 处理它

时间:2013-01-17 16:44:00

标签: php

我正在构建一些常见的类对象,这些对象将定期包含在$ _SESSION对象中。我了解到,在向会话添加对象时,有时可以添加对象而不进行序列化,但它不可靠,所以我先进行序列化,每次都可以正常工作。

我发现以下内容令人难以置信的tedius / repetive和clunky ......就像我必须从会话中检查对象做一些工作然后记得以正确的方式检查它。是否有更好/更有创意的方式,也是有效和可重复使用的。帮助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 个答案:

答案 0 :(得分:0)

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

e.g。

public function __sleep() {
    return array('these', 'are', 'property', 'identifiers');
}

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

<?php

class Foo{
    public $id;
}

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

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

我能发现的唯一区别是标准自动反序列化会在会话加载(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);

答案 3 :(得分:0)

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