Persisting PHP sessions into mongodb (allows NLB without affinity)
<?php | |
// all default values | |
MongoSessionPersistence::create() | |
->connect() | |
->register(); | |
// connect to concrete server/db | |
MongoSessionPersistence::create() | |
->connect('mongodb://mongo_server:27017', 'databaseName') | |
->useLifeTime(60*60) // lifetime=1 hour | |
->register(); | |
// use existing database connection | |
MongoSessionPersistence::create() | |
->useCollection($db->phpSessionStoreCollection) | |
->register(); | |
?> |
<?php | |
class MongoSessionPersistence implements SessionHandlerInterface | |
{ | |
private $collection=null; | |
private $lifeTime; | |
public function register() | |
{ | |
if(is_null($this->collection)) | |
$this->connect(); | |
$result = session_set_save_handler($this); | |
return $result; | |
} | |
public static function create(){ | |
return new MongoSessionPersistence(); | |
} | |
public function useLifeTime($lifetime){ | |
$this->lifeTime = $lifetime; | |
return $this; | |
} | |
public function useCollection(MongoCollection $collection){ | |
$this->collection = $collection; | |
$this->ensureIndex(); | |
return $this; | |
} | |
public function connect($server = 'mongodb://localhost:21017', | |
$database = 'test', | |
$collection = 'php_session') | |
{ | |
return $this->useCollection((new MongoClient($server)) | |
->selectDB($database)->selectCollection($collection)); | |
} | |
function __construct() | |
{ | |
$this->lifeTime = intVal(get_cfg_var('session.gc_maxlifetime')); | |
} | |
/** | |
* PHP >= 5.4.0<br/> | |
* Close the session | |
* @link http://php.net/manual/en/sessionhandlerinterface.close.php | |
* @return bool <p> | |
* The return value (usually TRUE on success, FALSE on failure). | |
* Note this value is returned internally to PHP for processing. | |
* </p> | |
*/ | |
public function close() | |
{ | |
// do nothing | |
return true; | |
} | |
/** | |
* PHP >= 5.4.0<br/> | |
* Destroy a session | |
* @link http://php.net/manual/en/sessionhandlerinterface.destroy.php | |
* @param int $session_id The session ID being destroyed. | |
* @return bool <p> | |
* The return value (usually TRUE on success, FALSE on failure). | |
* Note this value is returned internally to PHP for processing. | |
* </p> | |
*/ | |
public function destroy($session_id) | |
{ | |
$this->collection->remove(['_id' => $session_id]); | |
return true; | |
} | |
/** | |
* PHP >= 5.4.0<br/> | |
* Cleanup old sessions | |
* @link http://php.net/manual/en/sessionhandlerinterface.gc.php | |
* @param int $maxlifetime <p> | |
* Sessions that have not updated for | |
* the last maxlifetime seconds will be removed. | |
* </p> | |
* @return bool <p> | |
* The return value (usually TRUE on success, FALSE on failure). | |
* Note this value is returned internally to PHP for processing. | |
* </p> | |
*/ | |
public function gc($maxlifetime) | |
{ | |
// do nothing, actual GC performed by MongoDB ttl index | |
return true; | |
} | |
/** | |
* PHP >= 5.4.0<br/> | |
* Initialize session | |
* @link http://php.net/manual/en/sessionhandlerinterface.open.php | |
* @param string $save_path The path where to store/retrieve the session. | |
* @param string $session_id The session id. | |
* @return bool <p> | |
* The return value (usually TRUE on success, FALSE on failure). | |
* Note this value is returned internally to PHP for processing. | |
* </p> | |
*/ | |
public function open($save_path, $session_id) | |
{ | |
// do nothing | |
return true; | |
} | |
/** | |
* PHP >= 5.4.0<br/> | |
* Read session data | |
* @link http://php.net/manual/en/sessionhandlerinterface.read.php | |
* @param string $session_id The session id to read data for. | |
* @return string <p> | |
* Returns an encoded string of the read data. | |
* If nothing was read, it must return an empty string. | |
* Note this value is returned internally to PHP for processing. | |
* </p> | |
*/ | |
public function read($session_id) | |
{ | |
$obj = $this->collection->findOne(['_id' => $session_id]); | |
if ($obj) { | |
$data = $obj['data']; | |
return $data->bin; | |
} | |
return ''; | |
} | |
/** | |
* PHP >= 5.4.0<br/> | |
* Write session data | |
* @link http://php.net/manual/en/sessionhandlerinterface.write.php | |
* @param string $session_id The session id. | |
* @param string $session_data <p> | |
* The encoded session data. This data is the | |
* result of the PHP internally encoding | |
* the $_SESSION superglobal to a serialized | |
* string and passing it as this parameter. | |
* Please note sessions use an alternative serialization method. | |
* </p> | |
* @return bool <p> | |
* The return value (usually TRUE on success, FALSE on failure). | |
* Note this value is returned internally to PHP for processing. | |
* </p> | |
*/ | |
public function write($session_id, $session_data) | |
{ | |
// obtain proper time from mongodb server | |
$ts = $this->collection->db->command(['serverStatus' => 1 | |
, 'globalLock' => 0 | |
, 'metrics' => 0 | |
, 'repl' => 0 | |
, 'locks' => 0])['localTime']; | |
$ttl = new MongoDate($ts->sec + $this->lifeTime, $ts->usec); | |
$this->collection->save(['_id' => $session_id, | |
'data' => new MongoBinData($session_data), | |
'ttl' => $ttl]); | |
return true; | |
} | |
public function create_sid() | |
{ | |
$id = new MongoId(); | |
return "{$id}"; | |
} | |
private function ensureIndex() | |
{ | |
$this->collection->ensureIndex(['ttl' => 1], ['expireAfterSeconds' => 3600]); // +1 hour for sessions | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment