From 0faf38bd6fef2d2752058266842cd94cb1d77c6f Mon Sep 17 00:00:00 2001 From: Shinichi Urabe Date: Wed, 2 Sep 2015 20:00:03 +0900 Subject: [PATCH] (refs #3835) Prepared the preset configuration for using redis. --- config/OpenPNE.yml.sample | 4 +- lib/config/opProjectConfiguration.class.php | 5 + lib/user/opRedisSessionStorage.class.php | 209 ++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 lib/user/opRedisSessionStorage.class.php diff --git a/config/OpenPNE.yml.sample b/config/OpenPNE.yml.sample index 99ffb95..a6d4609 100644 --- a/config/OpenPNE.yml.sample +++ b/config/OpenPNE.yml.sample @@ -59,8 +59,8 @@ sid_secret: "" ###################################### # セッションストレージ設定 (Configure Session storage) -# name の値には、 file, database, memcache の他、任意のセッションストレージクラス名が使用できます -# ("file", "database", "memcached" and any class names of session storage class as value of "name") +# name の値には、 file, database, memcache, redis の他、任意のセッションストレージクラス名が使用できます +# ("file", "database", "memcached", "redis" and any class names of session storage class as value of "name") # database を選択した場合、扱えるセッション ID の文字列長 128 までとなります。必要に応じて session.hash_function と session.hash_bits_per_character の値を調節してください # (If you use "database", you can handle 128 length session id. Tune session.hash_function and session.hash_bits_per_character for your needs) session_storage: diff --git a/lib/config/opProjectConfiguration.class.php b/lib/config/opProjectConfiguration.class.php index c2cf0a3..0890bcd 100644 --- a/lib/config/opProjectConfiguration.class.php +++ b/lib/config/opProjectConfiguration.class.php @@ -89,6 +89,11 @@ class opProjectConfiguration extends sfProjectConfiguration 'db_time_col' => 'time', ), (array)$options, $params)); } + elseif ('redis' === $name) + { + sfConfig::set('sf_factory_storage', 'opRedisSessionStorage'); + sfConfig::set('sf_factory_storage_parameters', array_merge((array)$options, $params)); + } elseif ('file' !== $name) { sfConfig::set('sf_factory_storage', $name); diff --git a/lib/user/opRedisSessionStorage.class.php b/lib/user/opRedisSessionStorage.class.php new file mode 100644 index 0000000..8abcc82 --- /dev/null +++ b/lib/user/opRedisSessionStorage.class.php @@ -0,0 +1,209 @@ + + */ +class opRedisSessionStorage extends sfSessionStorage +{ + protected $redis = null; + + protected $defaults = array( + 'persistent' => true, + 'host' => 'localhost', + 'port' => 6379, + 'database' => 0, + 'timeout' => 60, + ); + + /** + * Available options: + * + * - host: The default host (default to localhost) + * - port: The port for the default server (default to 6379) + * - database: The default database (default to 0) + * - persistent: true if the connection must be persistent, false otherwise (true by default) + * + * @param array $options An associative array of options + * + * @see sfSessionStorage + */ + public function initialize($options = array()) + { + $isAutoStart = true; + if (isset($options['auto_start'])) + { + $isAutoStart = $options['auto_start']; + } + // disable auto_start + $options['auto_start'] = false; + + // initialize the parent + parent::initialize($options); + + if (!class_exists('Redis')) + { + throw new sfInitializationException('You must have redis installed.'); + } + + $this->redis = new Redis; + + // use this object as the session handler + session_set_save_handler( + array($this, 'sessionOpen'), + array($this, 'sessionClose'), + array($this, 'sessionRead'), + array($this, 'sessionWrite'), + array($this, 'sessionDestroy'), + array($this, 'sessionGC') + ); + + if ($isAutoStart && !parent::$sessionStarted) + { + // start our session + session_start(); + parent::$sessionStarted = true; + } + } + + /** + * Closes a session. + * + * @return boolean true, if the session was closed, otherwise false + */ + public function sessionClose() + { + // do nothing + return true; + } + + /** + * Opens a session. + * + * @param string $path (ignored) + * @param string $name (ignored) + * @throws sfInitializationException If unable to connect to the redis server or select to redis database. + * + * @return boolean true, if the session was opened, otherwise an exception is thrown + */ + public function sessionOpen($path = null, $name = null) + { + $options = array_merge($this->defaults, $this->options); + + $method = $options['persistent'] ? 'pconnect' : 'connect'; + $host = $options['host']; + $port = (int) $options['port']; + $database = (int) $options['database']; + $timeout = (int) $options['timeout']; + + if (!$this->redis->$method($host, $port, $timeout)) + { + throw new sfInitializationException(sprintf('Unable to connect to the redis server (%s:%s).', $host, $port)); + } + + if (!$this->redis->select($database)) + { + throw new sfInitializationException(sprintf('Unable to select to the redis database (number:%d).', $database)); + } + + return true; + } + + /** + * Destroys a session. + * + * @param string $id A session ID + * + * @return bool true, if the session was destroyed, otherwise an exception is thrown + */ + public function sessionDestroy($id) + { + return $this->redis->delete($id); + } + + /** + * Cleans up old sessions. + * + * @param int $lifetime The lifetime of a session + * + * @return bool true, if old sessions have been cleaned, otherwise an exception is thrown + */ + public function sessionGC($lifetime) + { + // do nothing + return true; + } + + /** + * Reads a session. + * + * @param string $id A session ID + * + * @return string The session data if the session was read or created + */ + public function sessionRead($id) + { + return (string)$this->redis->get($id); + } + + /** + * Writes session data. + * + * @param string $id A session ID + * @param string $data A serialized chunk of session data + * + * @return bool true, if the session was written, otherwise an exception is thrown + */ + public function sessionWrite($id, $data) + { + if (!$id || !$data) + { + return false; + } + + $lifetime = ini_get('session.gc_maxlifetime'); + + return $this->redis->setex($id, (int) $lifetime, $data); + } + + /** + * Regenerates id that represents this storage. + * + * @param boolean $destroy Destroy session when regenerating? + */ + public function regenerate($destroy = true) + { + if (self::$sessionIdRegenerated) + { + return false; + } + + $currentId = session_id(); + + parent::regenerate($destroy); + + $newId = session_id(); + $this->sessionRead($newId); + + return $this->sessionWrite($newId, $this->sessionRead($currentId)); + } + + /** + * Executes the shutdown procedure. + */ + public function shutdown() + { + parent::shutdown(); + } +} -- 2.5.0