2012-06-06 51 views
2

我正在使用一个PHP会话管理器类来处理MongoDB中的用户会话,但它不工作,我不能为我的生活找出原因。会话变量设置成功,但不会保留到其他页面中。与MongoDB的连接不是问题。我确定这个问题与session_set_save_handler有关,因为如果我评论这个函数,本地PHP会话处理工作正常。php/mongodb会话管理器,session_set_save_handler()问题

在此先感谢您的帮助。

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

?> 

回答

2

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

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

register_shutdown_function('session_write_close'); 

除了这个(因为这是几乎可以肯定发生),用于更新查询不以$开始选项(我犯了一个错误我自己无数次),你需要upsert没有$upsert

+0

用'register_shutdown_function('session_write_close')替换'session_write_close()'并且没有改变。 :\ – Scott

+0

你已经把它放在你的析构函数中,到那时它已经太晚了,因为关闭已经在进行中。把它放在你的构造函数中,你根本不需要析构函数。 – Leigh

+0

如上所示进行更改,但仍无法正常工作。 – Scott