RpcSession.php 4.85 KB
<?php
/**
 * Created by PhpStorm.
 * User: Zip
 * Date: 15/12/23
 * Time: 20:07
 */

namespace Hood\Core\Session;

use Hood\Core\Support\Str;
use Hood\Core\Root;
use Hood\Cache\Memcached as mcCache;
use Hood\Utils\Rpc\Factory;

class RpcSession extends Root implements SessionHandlerInterface
{
    /**
     * session 前缀
     * @var string
     */
    private $sessionPrefix = 'session:';

    /**
     * Session数据就自动删除时间
     * @var int
     */
    private $gcMaxLifeTime = 86400;

    private $sessionOptions = array(
        'use_cookies',
        'auto_start',
        'serialize_handler',
        'cookie_lifetime',
        'cookie_path',
        'cookie_domain',
        'use_cookies',
        'cache_expire',
        'gc_maxlifetime'
    );

    private $serviceClient;

    private $sessionName = null;

    private $domain = null;

    private $serviceUrl = '';

    private $rpcType = 'yar';

    /**
     * 初始化
     */
    public function __construct($serviceUrl)
    {
        session_set_save_handler(
            array(&$this, "open"),
            array(&$this, "close"),
            array(&$this, "read"),
            array(&$this, "write"),
            array(&$this, "destroy"),
            array(&$this, "gc")
        );
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            register_shutdown_function('session_write_close');
        }
        ini_set("session.use_cookies", 1);
        ini_set('use_only_cookies', 0);
        ini_set('session.cookie_path', '/');
        ini_set('session.gc_maxlifetime', $this->gcMaxLifeTime);
        $this->serviceUrl = $serviceUrl;
    }

    public function setRpcType($type)
    {
        $this->rpcType = $type;
        return $this;
    }

    public function setSessionName($sessionName)
    {
        if (!empty($sessionName)) {
            $this->sessionName = $sessionName;
        }
        return $this;
    }

    public function setDomain($domain)
    {
        if (!empty($domain)) {
            $this->domain = $domain;
        }
        return $this;
    }

    public function setOption()
    {
        if (!empty($this->sessionName) && is_string($this->sessionName)) {
            ini_set("session.name", $this->sessionName);
        }
        if (empty($this->domain)) {
            ini_set("session.cookie_domain", $this->currentDomain());
        } else {
            ini_set("session.cookie_domain", '.' . $this->domain);
        }
    }


    public function currentDomain()
    {
        if (!isset($_SERVER['HTTP_HOST'])) {
            return '';
        }
        if (ip2long($_SERVER['HTTP_HOST']) == false) {
            return '.' . preg_replace("/^(.*\.)?([^.]*\..*)$/", "$2", $_SERVER['HTTP_HOST']);
        }
        return $_SERVER['HTTP_HOST'];
    }

    /**
     * @return serviceClient
     */
    private function rpc()
    {
        if (empty($this->serviceUrl)) {
            throw new \Exception('Session Rpc Service is Null.');
        }
        $this->setOption();
        if (empty($this->serviceClient)) {
            $this->serviceClient = Factory::getInstance($this->serviceUrl, $this->rpcType);
        }
        return $this->serviceClient;
    }

    /**
     * 设置session参数
     * @param array $options
     * @return $this
     */
    public function setSessionOptions(array $options)
    {
        foreach ($options as $key => $val) {
            if (isset($this->sessionOptions[$key])) {
                ini_set('session.' . $key, $val);
            }
        }
        return $this;
    }

    /**
     * 打开Session
     * @param string $savePath
     * @param string $sessionID
     * @return bool
     */
    public function open($savePath, $sessionID)
    {
        return $this->rpc()->open($savePath, $sessionID);
    }

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

    /**
     * 读取缓存
     * @param string $sessionID
     * @return mixed|string
     */
    public function read($sessionID)
    {
        return $this->rpc()->read($this->sessionPrefix . $sessionID);
    }

    /**
     * 写入Session
     * @param string $sessionID
     * @param string $sessionData
     * @return bool
     */
    public function write($sessionID, $sessionData)
    {
        $return = $this->rpc()->write($this->sessionPrefix . $sessionID, $sessionData, $this->gcMaxLifeTime);
        return $return;
    }

    /**
     * 注销Session
     * @param int $sessionID
     * @return bool
     */
    public function destroy($sessionID)
    {
        return $this->rpc()->destroy($this->sessionPrefix . $sessionID);
    }

    public function gc($maxlifetime)
    {
        return $this->rpc()->gc($maxlifetime);
    }

    public function __destruct()
    {
        session_write_close();
    }

    public function generateSessionId()
    {
        return sha1(uniqid('', true) . Str::random(25) . microtime(true));
    }
}