session保存到redis

/**
 * Store PHP sessions in redis.
 * 
 * Depends on {@link http://github.com/nrk/predis/ Predis}
 * 
 * @author Mickael Magniez <mickaelmagniez@gmail.com>
 * 
 * @version 0.1
 * 
 * @license http://www.gnu.org/licenses/lgpl-3.0.html
 * 
 * <code>
 * <?php 
 *    require_once 'RedisSession.php';
 *    
 *    RedisSession::init ( array ( 
 *      'session_name' => 'redis_sess', 
 *      'cookie_path' => '/', 
 *      'cookie_domain' => '.acme.org', 
 *      'lifetime' => 3600, 
 *      'server' => array ( 
 *          'host' => 'redis.acme.org', 
 *          'port' => 6379 ) ) );
 * ?>
 * </code>
 */
class RedisSession {
    /**
     * Default config
     * @var array
     */
    private $_config = array ( 
            'session_name' => 'redis_sess', 
            'cookie_path' => '/', 
            'cookie_domain' => '.example.com', 
            'lifetime' => 0, 
            'server' => array ( 
                    'host' => '127.0.0.1', 
                    'port' => 6379 ) );
    
    /**
     * Predis Object
     * @var Redis
     */
    private $_redis;
    
    /**
     * Current session id, for optimization purpose (cf method write())
     * @var string
     */
    private $_id = '';
    
    /**
     * RedisSession instance, prevent to bind several session manager 
     * @var RedisSession
     */
    private static $_instance = null;

    /**
     * Initialize Redis Session (the only method to call)
     * 
     * @param array $config Session configuration (cf field definition)
     */
    public static function init ( $config = array() ) {
        if (!self::$_instance instanceof self) {
            self::$_instance = new self ( $config );
        } else {
            throw new Exception ( 'RedisSession already initialized' );
        }
    }

    /**
     * Default constructor.
     *
     * @param array $config Session configuration (cf field definition)
     * 
     * @throws Exception
     */
    private function __construct ( $config = array() ) {
        if (!empty ( $config )) {
            if (!( isset ( $config ['cookie_path'] ) && isset ( $config ['cookie_domain'] ) 
                && isset ( $config ['session_name'] )
                && isset ( $config ['lifetime'] ) && is_int ( $config ['lifetime'] ) 
                && isset ( $config ['server'] ) && is_array ( $config ['server'] ) && isset ( $config ['server'] ['host'] ) && isset ( $config ['server'] ['port'] ) && is_int ( $config ['server'] ['port'] ) 
                )) {
                throw new Exception ( 'Bad configuration, see documentation' );
            }
            $this->_config = $config;
        }
        
        if ($this->_init ()) {
            session_set_save_handler ( array ( 
                    &$this, 
                    'open' ), array ( 
                    &$this, 
                    'close' ), array ( 
                    &$this, 
                    'read' ), array ( 
                    &$this, 
                    'write' ), array ( 
                    &$this, 
                    'destroy' ), array ( 
                    &$this, 
                    'gc' ) );
            
            ini_set ( 'session.auto_start', 0 );
            
            // No garbage collector, Redis exiration do it
            ini_set ( 'session.gc_probability', 0 );
            ini_set ( 'session.gc_divisor', 0 );
            
            session_cache_limiter ( 'nocache' );
            session_set_cookie_params ( $this->_config ['lifetime'], $this->_config ['cookie_path'], $this->_config ['cookie_domain'] );
            
            session_name ( $this->_config ['session_name'] );
            session_start ();
        } else {
            throw new Exception ( 'Cannot initiliaze Redis Session' );
        }
    }

    /**
     * Initialize Redis.
     *
     */
    private function _init () {
        $this->_redis = new Redis ();
        return $this->_redis->connect ( $this->_config ['server'] ['host'], $this->_config ['server'] ['port'] );
    }

    /**
     * Open just save sessoin name for key prefix as we already have an open connection.
     *
     * @return bool
     */
    public function open ( $savePath, $sessionName ) {
        $this->_config ['keyprefix'] = $sessionName . '::';
        return true;
    }

    /**
     * @return bool
     */
    public function close () {
        return true;
    }

    /**
     * Read the session data.
     *
     * @param string $id
     * @return string
     */
    public function read ( $id ) {
        return $this->_redis->get ( $this->_buildKey ( $id ) );
    }

    /**
     * Write data to the session. 
     *
     * @param string  $id
     * @param mixed   $data
     * @return bool
     */
    public function write ( $id, $data ) {
        // This might be the first set for this session key, so we have to check if it's already exists in redis
        if ($this->_id !== $id) {
            // Perform getset to check if session already exists in redis
            if ($this->_redis->getSet ( $this->_buildKey ( $id ), $data ) === false) {
                // session doesn't exists in redis, so we have to set expiration
                $this->_redis->expire ( $this->_buildKey ( $id ), $this->_config ['lifetime'] );
            }
            // Backup id, so we'll know that expiration has already been set, we'll avoid to perform getset on the next write 
            $this->_id = $id;
        } else {
            // This is not the first write in script execution, just update value
            $this->_redis->set ( $this->_buildKey ( $id ), $data );
        }
        return true;
    }

    /**
     * Destroys the session by removing the entry.
     * 
     * @param string $id
     * @return bool
     */
    public function destroy ( $id ) {
        $this->_redis->delete ( $this->_buildKey ( $id ) );
        session_destroy ();
        return true;
    }

    /**
     * Garbage collection. Done by redis.
     *
     * @return bool
     */
    public function gc () {
        return true;
    }

    /**
     * Build Redis entry key.
     * 
     * @param string $id
     * @return string
     */
    private function _buildKey ( $id ) {
        return $this->_config ['keyprefix'] . $id;
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值