PHP/MongoDB 会话管理器,session_set_save_handler() 问题


php/mongodb session manager, session_set_save_handler() issue

我正在使用一个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();
?>
write

对象销毁后调用。您的$_mongo对象在您使用它时已被销毁。

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

register_shutdown_function('session_write_close');

除此之外(因为这几乎肯定会发生),更新查询的选项不以$开头(我自己犯过无数次的错误),您需要upsert不要$upsert