【问题标题】:Why can't I store a PHP class instance as a SESSION variable为什么我不能将 PHP 类实例存储为 SESSION 变量
【发布时间】:2010-10-10 20:22:26
【问题描述】:

我有一个 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 脚本 因此类方法应该是已知的和可用的。

我在这里错过了什么?

【问题讨论】:

  • 尽量避免使用@;只需正确编写代码,以免出现任何错误。

标签: php class session variables instance


【解决方案1】:

您可能需要serialize $st 对象/变量才能存储它。这将确保所有内容都保存到会话中。这绝对是使用object oriented 代码的方法。当你想再次使用数据时,你必须unserialize它。

【讨论】:

  • 会话变量自动序列化和反序列化。
【解决方案2】:

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

【讨论】:

  • 如果我按照您的建议移动定义,则会话数组返回的值为空。
  • 你有 display_errors on 和 error_reporting E_ALL 吗?你能确保第一个位实际上正在运行($comd=="init")吗?
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

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

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

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

    【讨论】:

      【解决方案5】:

      这是难以单独调试的事情之一。在 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:..........
      

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

      【讨论】:

        【解决方案6】:

        试试这个:

            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());
            }
        

        【讨论】:

          猜你喜欢
          • 2019-06-06
          • 2013-11-23
          • 2011-03-24
          • 1970-01-01
          • 1970-01-01
          • 2020-09-29
          • 2013-11-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多