Php PDO准备失败

Php PDO准备失败,php,session,pdo,session-set-save-handler,Php,Session,Pdo,Session Set Save Handler,我正在试验PHP的session\u set\u save\u处理程序,我想使用PDO连接来存储会话数据 我将此函数用作写操作的回调: function _write($id, $data) { logger('_WRITE ' . $id . ' ' . $data); try { $access = time(); $sql = 'REPLACE INTO sessions SET id=:id, access=:access, data=:d

我正在试验PHP的
session\u set\u save\u处理程序
,我想使用PDO连接来存储会话数据

我将此函数用作写操作的回调:

function _write($id, $data) {
    logger('_WRITE ' . $id . ' ' . $data);
    try {
        $access = time();
        $sql = 'REPLACE INTO sessions SET id=:id, access=:access, data=:data';
        logger('This is the last line in this function that appears in the log.');
        $stmt = $GLOBALS['db']->prepare($sql);
        logger('This never gets logged! :(');
        $stmt->bindParam(':id', $id, PDO::PARAM_STR);
        $stmt->bindParam(':access', $access, PDO::PARAM_INT);
        $stmt->bindParam(':data', $data, PDO::PARAM_STR);
        $stmt->execute();
        $stmt->closeCursor();
        return true;
    } catch (PDOException $e) {
        logger('This is never executed.');
        logger($e->getTraceAsString());
    }
}
前两条日志消息始终显示,但紧跟在
$stmt=$GLOBALS['db']->prepare($sql)
之后的第三条日志消息从未进入日志文件,也没有异常的痕迹

会话数据库表保持为空

来自
\u close
回调的日志消息始终存在

以下是我连接数据库的方式:

$db = new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
我有PHP5.2.10

我试图简单地用一个“手动准备的”
$sql
内容运行
$GLOBALS['db']->exec($sql)
,但仍然以静默方式失败。查询本身是正确的,我可以通过db控制台执行它


编辑: 在沃尔克发现了我发现的问题后,这解释了这种奇怪现象背后的原因。也许它也能为其他人提供信息


第二次编辑: 最不痛苦、最神奇的解决方案是,我必须将下面的函数调用添加到前端控制器(main index.php)文件的最末端:


我打赌:$GLOBALS['db']未设置或不是pdo的实例(不再?),因此出现
PHP致命错误:对非对象调用成员函数prepare(),PHP退出

$sql = 'REPLACE INTO sessions SET id=:id, access=:access, data=:data';
logger('This is the last line in this function that appears in the log.');
if ( !isset($GLOBALS['db']) ) {
  logger('there is no globals[db]');
  return;
}
else if ( !is_object($GLOBALS['db']) ) {
  logger('globals[db] is not an object');
  return;
}
else if ( !($GLOBALS['db'] instanceof PDO) ) {
  logger('globals[db] is not a PDO object');
  return;
}
else {
  logger('globals[db] seems ok');
}

$stmt = $GLOBALS['db']->prepare($sql);
logger('This never gets logged! :(');

也许PDO无法识别替换为语法。如果底层DB access库不直接支持准备好的语句,PDO将模拟它们,并且在其可能的语句类型列表中可能没有REPLACE-INTO

在prepare调用后立即尝试检查
$stmt->errorCode()

如果这是mysql,您可以尝试按如下方式重写准备好的语句:

INSERT INTO sessions (id, access, data)
VALUES(:id, :access, :data)
ON DUPLICATE KEY UDPATE
    access=VALUES(access), data=VALUES(data);

看看这是否能让您走得更远。

我觉得无法通过
$GLOBALS[]
访问资源数据类型。关于引用的处理方式之类的。如果您想幽默我的直觉,请尝试以下函数声明:

function _write($id, $data) {
    global $db;
    logger('_WRITE ' . $id . ' ' . $data);
    try {
而不是这个:

$stmt = $GLOBALS['db']->prepare($sql);
试一试

您还可以尝试捕获普通的旧
异常
s,而不是
PDOException
s;它可能会被这件事缠住


希望这有帮助

确保您有
错误报告(-1)
enabled@Gordon:什么都没有改变。我已经有了这个设置:
错误报告(E|u ALL | E|u STRICT)
好的。顺便说一句-1与您的设置相同,只是更便于记忆;)使用
global
和使用
$global
引用全局变量之间绝对没有区别。同样,普通的
异常
也没有任何区别。谢谢你的帮助。事实上,我正在使用MySQL 5.1,但是重写查询没有帮助。我甚至试图将它重写为一个完全无害且无用的
SELECT
,但在
prepare
之后,它仍然停止了,没有任何通知。因此,我无法检查
errorCode
。这真的很奇怪。我们这里有个赢家!:)事实上,我记录了“没有全局[db]”消息。我不知道为什么会这样,但这是一个非常有用的线索。非常感谢你的帮助,非常感谢。
$stmt = $GLOBALS['db']->prepare($sql);
$stmt = $db->prepare($sql);