Skip to content

Instantly share code, notes, and snippets.

@j
Created October 7, 2011 17:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save j/1270865 to your computer and use it in GitHub Desktop.
Save j/1270865 to your computer and use it in GitHub Desktop.
Create a memcache session storage with optional storage backup
framework:
session:
default_locale: %locale%
auto_start: true
lifetime: 7200
storage_id: memcache_session_storage
parameters:
pdo.db_options:
db_table: session
db_id_col: session_id
db_data_col: session_value
db_time_col: session_time
memcache.options:
host: localhost
port: 11211
services:
memcache_session_storage:
class: JStout\MainBundle\Session\MemcacheSessionStorage
arguments: [@memcache, %session.storage.options%, %memcache.options%, @pdo_session_storage]
pdo_session_storage:
class: Symfony\Component\HttpFoundation\SessionStorage\PdoSessionStorage
arguments: [@pdo, %session.storage.options%, %pdo.db_options%]
memcache:
class: Memcache
<?php
namespace JStout\MainBundle\Session;
use Symfony\Component\HttpFoundation\SessionStorage\NativeSessionStorage;
/**
* MemcacheSessionStorage.
*/
class MemcacheSessionStorage extends NativeSessionStorage
{
private $memcache;
private $storage;
private $lifetime;
/**
* Constructor.
*
* @param \Memcache $memcache A memcache instance
* @param array $options An associative array of session options
* @param array $memcacheOptions An associative array of memcache options
* @param Symfony\Component\HttpFoundation\SessionStorage\NativeSessionStorage $storage An instance of NativeSessionStorage
*
* @see NativeSessionStorage::__construct()
*/
public function __construct(\Memcache $memcache, array $options = array(), array $memcacheOptions = array(), NativeSessionStorage $storage = null)
{
$this->memcache = $memcache;
$this->started = false;
if (!array_key_exists('host', $memcacheOptions)) {
throw new \InvalidArgumentException('You must provide the "host" option for a Memcache.');
}
if (!array_key_exists('port', $memcacheOptions)) {
throw new \InvalidArgumentException('You must provide the "port" option for a Memcache.');
}
if (array_key_exists('lifetime', $options)) {
$this->lifetime = $options['lifetime'];
} else {
// get lifetime from php config
$this->lifetime = intval(ini_get('session.gc_maxlifetime'));
}
@$this->memcache->connect($memcacheOptions['host'], $memcacheOptions['port']);
// see if memcache server is available
if (!$this->memcache->getServerStatus($memcacheOptions['host'])) {
$this->memcache = null;
}
$this->storage = $storage;
parent::__construct($options);
}
/**
* Starts the session.
*
* @api
*/
function start()
{
if (self::$sessionStarted) {
return;
}
// if memcache server is down, use secondary session handler, otherwise throw exception
if (null === $this->memcache) {
if (null !== $this->storage && method_exists($this->storage, 'start')) {
return $this->storage->start();
} else {
throw new \Exception('No session storages are available.');
}
}
session_set_save_handler(
array($this, 'sessionOpen'),
array($this, 'sessionClose'),
array($this, 'sessionRead'),
array($this, 'sessionWrite'),
array($this, 'sessionDestroy'),
array($this, 'sessionGC')
);
parent::start();
}
/**
* Opens a session.
*
* @param string $path (ignored)
* @param string $name (ignored)
*
* @return Boolean true, if the session was opened, otherwise an exception is thrown
*/
public function sessionOpen($path = null, $name = null)
{
return true;
}
/**
* Closes a session.
*
* @return Boolean true, if the session was closed, otherwise false
*/
public function sessionClose()
{
// do nothing
return true;
}
/**
* Destroys a session.
*
* @param string $id A session ID
*
* @return Boolean true, if the session was destroyed, otherwise an exception is thrown
*
* @throws \RuntimeException If the session cannot be destroyed
*/
public function sessionDestroy($id)
{
if (null !== $this->memcache) {
$this->memcache->delete($id);
}
if (null !== $this->storage && method_exists($this->storage, 'sessionDestroy')) {
$this->storage->sessionDestroy($id);
}
return true;
}
/**
* Cleans up old sessions.
*
* @param int $lifetime The lifetime of a session
*
* @return Boolean true, if old sessions have been cleaned, otherwise an exception is thrown
*
* @throws \RuntimeException If any old sessions cannot be cleaned
*/
public function sessionGC($lifetime)
{
if (null !== $this->storage && method_exists($this->storage, 'sessionGC')) {
$this->storage->sessionGC($lifetime);
}
return true;
}
/**
* Reads a session.
*
* @param string $id A session ID
*
* @return string The session data if the session was read or created, otherwise an exception is thrown
*
* @throws \RuntimeException If the session cannot be read
*/
public function sessionRead($id)
{
$data = '';
if (null !== $this->memcache) {
$data = $this->memcache->get($id);
}
if ($data === false) {
if (null !== $this->storage && method_exists($this->storage, 'sessionRead')) {
return $this->storage->sessionRead($id);
} else {
return array();
}
}
if (null !== $this->memcache) {
$this->memcache->set($id, $data, false, $this->lifetime);
}
return $data;
}
/**
* Writes session data.
*
* @param string $id A session ID
* @param string $data A serialized chunk of session data
*
* @return Boolean true, if the session was written, otherwise an exception is thrown
*
* @throws \RuntimeException If the session data cannot be written
*/
public function sessionWrite($id, $data)
{
$result = false;
if (null !== $this->memcache) {
$result = $this->memcache->set($id, $data, false, $this->lifetime);
}
if (null !== $this->storage && method_exists($this->storage, 'sessionWrite')) {
$this->storage->sessionWrite($id, $data);
}
return $result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment