使用会话处理程序时,未找到交替类错误

时间:2014-06-23 22:33:35

标签: php session

首先,如果相关,则在会话处理程序中。此函数是写入数据库的函数,并与我的其他函数一起传递给session_set_save_handler

session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy', 'sess_gc');

我有这段代码......

$qid = "select count(*) as total
        from zen_sessions
        where sesskey = '" . $key . "'";

if(!class_exists('DB'))
    require_once dirname(dirname(__FILE__)).'/class/DB.class.php';
var_dump(new DB());                      //this is line 109
$total = DB::select_one($qid);

条件和var_dump用于测试。奇怪的是,有时候它可以正常工作,而有些则给我一个错误:

Fatal error: Class 'DB' not found in /path/to/file/session_functions.php on line 109

我无法想象这有什么不会在需求而不是var_dump崩溃,为什么只有时呢?

提前感谢任何见解。

编辑 - 回复评论/问题:

以下代码的结果

var_dump(class_exists('DB', false)); 
var_dump(is_file(dirname(__DIR__).'/class/DB.class.php')); 

是:

bool(false) bool(true) 

在尝试要求之前和在require之后的相同结果之前(或者当它没有给我一个错误时为true) 看起来像:

bool(true) bool(true) object(DB)#3 (0) { } 

以前的代码块是每5页加载一次的结果,而错误是其他4的结果。

Edit2 - 新发现。

更奇怪的是根据manual我永远不会看到这些调试语句或错误

  

注意:

     

"写"在输出流之后才执行handler   关闭。因此,来自" write"中的调试语句的输出。处理器   将永远不会在浏览器中看到。如果需要调试输出,   建议将调试输出写入文件。

编辑3 - 为清晰起见的注释:

DB类应该已经自动加载(并且在应用程序的其他任何位置)class_exists和require仅用于测试目的。

编辑4 - 堆栈跟踪

我决定尝试在没有找到类来查看堆栈跟踪时抛出异常,这就是我得到的

Fatal error: Uncaught exception 'Exception' with message 'DB Class Not Found.' 
in /path/to/file/session_functions.php:108 
Stack trace: #0 [internal function]: sess_write('074dabb967260e9...', 'securityToken|s...') 
#1 {main} thrown in /path/to/file/session_functions.php on line 108 

3 个答案:

答案 0 :(得分:1)

我唯一可以想到可能造成这种情况的事情,来自于session_set_save_handler的PHP文档中的通知:

  

警告

     

如果在脚本终止中关闭会话,则会使用某些SAPI更改当前工作目录。可以使用session_write_close()关闭会话。

根据您的体验,我猜测当前的工作目录已更改,因此require_once找不到该文件。

我会尝试session_write_close();添加到您的函数中的某个位置,看看是否可以修复它。

不可否认,不确定为什么is_file在这种情况下会返回true,但也许值得一试。

答案 1 :(得分:1)

即使我不能确定,但​​我敢打赌,错误在其他地方,并且它只是按照你所描述的那样投射出来。

为了测试和调试代码,您需要使用PDT之类的调试器。但问题是你需要调试一部分超出调试器范围的代码,即会话编写者!要解决此问题,您可以使用session_write_close。你可以把它放在引导程序的末尾,如果你没有引导程序,你可以这样做:

<?php
function shutdown_function()
{
    session_write_close();
}

register_shutdown_function('shutdown_function');

然后通过设置断点,您可以从此处开始调试会话代码。如果我赢了赌注,请告诉我。

答案 2 :(得分:0)

尝试:

$save_handler = new DB();
session_set_save_handler($save_handler, true);

然后在你的类中映射read,write等函数。我遇到了一个类似的问题(关于一个没有找到的类的奇怪的随机错误)用redis实现HHVM的另一个用户的自定义保存处理程序解决方法,这就是我修复它的方法。如果您正在使用HipHopVirtualMachine(或者可能是其他类型的JIT编译器或应用程序缓存),有时您的项目可以缓存某些函数而不进行更新,从而产生这样的奇怪错误。通常重启fastcgi守护进程并为你的一个文件添加空格足以迫使它重新解释你的项目。