phpsessionpdosession-set-save-handler

PDO prepare silently fails


I'm experimenting with PHP's session_set_save_handler and I'd like to use a PDO connection to store session data.

I have this function as a callback for write actions:

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

The first two log messages always show up, but the third one right after $stmt = $GLOBALS['db']->prepare($sql) never makes it to the log file and there's no trace of an exception either.

The sessions db table remains empty.

The log message from the _close callback is always present.

Here's how I connect to the database:

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

I have PHP 5.2.10.

I tried to simply run $GLOBALS['db']->exec($sql) with a "manually prepared" $sql content, but it still failed silently. The query itself is all right I was able to execute it via the db console.


Edit:

After VolkerK has identified the problem I've found this article which explains the reason behind this weird phenomena. Perhaps it could be informative to others as well.


2nd edit:

The least painful, magic solution is that I had to add the below function call to the very end of my front controller (the main index.php) file:

session_write_close();

Solution

  • My bets are on: $GLOBALS['db'] is not set or not an instance of pdo (anymore?) and therefor a PHP Fatal error: Call to a member function prepare() on a non-object occurs and php bails out.

    $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! :(');