php / mongodb会话管理器,session_set_save_handler()问题

时间:2012-06-06 13:13:46

标签: php session mongodb session-set-save-handler

我正在使用一个PHP会话管理器类来处理MongoDB中的用户会话,但是它不起作用,我不能为我的生活找出原因。会话变量设置成功,但不会持久保存到其他页面中。与MongoDB的连接不是问题。我已经确定该问题与session_set_save_handler有关,因为如果我将该函数注释掉,本机PHP会话处理工作正常。

提前感谢您的帮助。

...
require('database.class.php');

class SessionManager {

const COLLECTION = 'sessions';
const SESSION_TIMEOUT = 600;
const SESSION_LIFESPAN = 3600;
const SESSION_NAME = 'mongosessid';
const SESSION_COOKIE_PATH = '/';
const SESSION_COOKIE_DOMAIN = '';

private $_mongo;
private $_collection;
private $_currentSession;

public function __construct() {
    $this->_mongo = DBConnection::instantiate();
    $this->_collection = $this->_mongo->getCollection(SessionManager::COLLECTION);

    register_shutdown_function('session_write_close'); 

    session_set_save_handler(
        array(&$this, 'open'),
        array(&$this, 'close'),
        array(&$this, 'read'),
        array(&$this, 'write'),
        array(&$this, 'destroy'),
        array(&$this, 'gc')
    );

    //Set session garbage collection period
    ini_set('session.gc_maxlifetime', SessionManager::SESSION_LIFESPAN);

    //Set session cookie config
    session_set_cookie_params(
        SessionManager::SESSION_LIFESPAN,
        SessionManager::SESSION_COOKIE_PATH,
        SessionManager::SESSION_COOKIE_DOMAIN
    );

    //Replace 'PHPSESSID' with 'mongosessid' as the session name
    session_name(SessionManager::SESSION_NAME);
    session_cache_limiter('nocache');

    session_start();

}   

public function open($path, $name) {
    return true;
}

public function close() {
    return true;
}

public function read($sessionId) {
    $query = array('session_id' => $sessionId,
                    'timedout_at' => array('$gte' => time()),
                    'expired_at' => array('$gte' => time() - SessionManager::SESSION_LIFESPAN)
                    );

    $result = $this->_collection->findOne($query);
    $this->_currentSession = $result;

    if (!isset($result['data'])) {
        return '';
    }

    return $result['data'];
}

public function write($sessionId, $data) {
    $expired_at = time() + self::SESSION_TIMEOUT;
    $new_obj = array('data' => $data,
                    'timedout_at' => time() + SessionManager::SESSION_TIMEOUT,
                    'expired_at' => (empty($this->_currentSession)) ? time() + SessionManager::SESSION_LIFESPAN : $this->_currentSession['expired_at']
                    );
    $query = array('session_id' => $sessionId);

    $this->_collection->update($query,
                                array('$set' => $new_obj),
                                array('$upsert' => TRUE)
                                );
}

public function destroy($sessionId) {
    $this->_collection->remove(array('session_id' => $sessionId));
    return TRUE;
}

public function gc() {
    $query = array('expired_at' => array('$lt' => time()));
    $this->_collection->remove($query);
    return TRUE;
}

}

$session = new SessionManager();

?>

1 个答案:

答案 0 :(得分:2)

在对象销毁后调用

write。当你使用它时,你的$_mongo对象已经被破坏了。

使用session_write_close()register_shutdown_function()来解决此问题。

register_shutdown_function('session_write_close');

除此之外(因为这几乎肯定会发生),更新查询的选项不是以$开头(我自己多次犯了一个错误),你需要{{1} } upsert