5

我有一个 PHP 脚本,它通过 Dojo Ajax xhrGet 调用以 2 种方式调用。第一次使用“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 脚本,因此类方法应该是已知且可用的。

我在这里想念什么?

4

6 回答 6

13

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

于 2009-03-02T18:54:30.870 回答
1

这是难以单独调试的事情之一。在 PHP Sessions 中存储实例化的对象总是有点棘手,并且不能 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:..........

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

于 2009-03-02T20:24:56.083 回答
1

您可能需要在存储 $st 对象/变量之前对其进行序列化。这将确保所有内容都保存到会话中。这绝对是面向对象代码的方式。当您想再次使用数据时,您必须对其进行反序列化

于 2009-03-02T18:52:47.380 回答
0

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

于 2009-03-02T18:55:34.330 回答
0

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

如果您打开 session.auto_start 那么将对象放入会话的唯一方法是使用加载类定义的 auto_prepend_file 加载其类定义,否则您将不得不序列化您的对象并在之后取消序列化它。

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

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

于 2009-03-02T18:56:40.693 回答
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());
    }
于 2012-03-29T16:13:28.470 回答