为什么我不能将PHP类实例存储为SESSION变量

时间:2009-03-02 18:43:14

标签: php class session variables instance

我有一个PHP脚本,它通过Dojo Ajax xhrGet调用以两种方式调用。 第一次使用“init”参数调用它会导致脚本创建StateList类的实例并读入状态名称的文件。

session_start();
@include('StateList.php');
require_once('phplog.php');

//start executing here
$comd=$_GET['nexturl'];
if($comd=="init") {
$st = new StateList("../data/statestxt.txt");
$_SESSION['statefile'] = $st;
}

第二次和另外一次,另一个xhrGet调用传递一个“getstate”参数,下面的代码试图从SESSION数组中获取StateList类的实例。

if($comd =="getstate") {
$st= $_SESSION['statefile'];
phplog("size=".$st->getSize());

}

但是,从不执行getSize()方法,也不能调用任何其他方法 在重构的StateList类实例上。

请注意,这是一个PHP脚本,它包含顶部的类定义 因此,类方法应该是已知的和可用的。

我在这里缺少什么?

6 个答案:

答案 0 :(得分:13)

您需要在调用session_start()之前包含类定义,否则该对象将不会被正确反序列化,并且将成为__PHP_Incomplete_Class的实例。否则你所拥有的应该可以正常工作。

答案 1 :(得分:1)

在存储之前,您可能需要serialize $ st对象/变量。这将确保将所有内容保存到会话中。这绝对是object oriented代码的方法。如果要再次使用数据,则必须unserialize

答案 2 :(得分:1)

这是难以独立调试的事情之一。在PHP会话中存储实例化对象总是有点棘手,并且不能100%保证可以正常工作。以下是一些常见的调试技巧,可以帮助您解决这个问题。

首先,检查您的apache错误日志。你得到一个“非对象错误调用方法”吗?如果是这样,这意味着您没有从会话中恢复对象。如果没有,是否有错误表明您的方法调用由于其他原因而失败?

其次,检查一下你的会话实际上是什么。

if($comd =="getstate") {
    $st= $_SESSION['statefile'];
    //get the class of st
    phplog("instance=".get_class($st));

    //get a reflection dump of st
    $ref = new ReflectionClass($st);
    $string = $ref->__toString();       
    phplog("reflection=".$string);
}   

第三,查看会话本身存储的序列化字符串值。你实际上存储一个序列化的对象?在你的开发环境中,将php.ini中的session.save_path ini值设置为/ tmp,(或使用ini_set方法执行相同的操作):

session.save_path = "/tmp"

然后检查在/ tmp(或任何文件夹)中创建的文件。您应该看到一个以:

开头的字符串
statefile:O:..........

实例化对象的类的名称也将包含在那里,以及保存到属性的值。

答案 3 :(得分:0)

如果要在会话中存储一个对象,它必须是link text。在PHP中序列化对象有很多问题,更不用说将它们存储在会话中了。我建议不要这样做,并为您的问题找到不同的解决方案。如果您打算这样做,您应该查看您应该在类中定义的“魔术方法”link text,以便在从会话中调用它时进行重新实现。

答案 4 :(得分:0)

您是否启用了session.auto_start?手册的会话页面指出,如果这样做,则必须以不同方式加载类定义:

  

如果打开session.auto_start,那么将对象放入会话的唯一方法是使用auto_prepend_file加载其类定义,在其中加载类定义,否则必须序列化对象并在之后对其进行反序列化。

http://php.net/manual/en/intro.session.php

正如该页面所说,对象的序列化/反序列化通常由PHP自动完成,但启用session.auto_start会改变它。

答案 5 :(得分:0)

试试这个:

    include('StateList.php');
    require_once('phplog.php');
    // start your session after including your class file
    session_start();

    //start executing here
    $comd=$_GET['nexturl'];
    if($comd=="init") {
    $st = new StateList("../data/statestxt.txt");
    $_SESSION['statefile'] = $st;
    } 

    if($comd =="getstate") {
    // the ampersand creates a reference, preserving any further changes to your session data
    $st = &$_SESSION['statefile'];
    phplog("size=".$st->getSize());
    }