Last active
July 30, 2016 08:30
-
-
Save dimzon/62eeb9b8561bcb9f0c6d to your computer and use it in GitHub Desktop.
Persisting PHP sessions into mongodb (allows NLB without affinity)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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(); | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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