• 周五. 9月 30th, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

php里少用到的session_module_name,以及session的key值限制,简单将session存储为json格式数据的方法

admin

11月 28, 2021

这个函数的作用就是动态的设置php.ini里的session_save_handler,配合session_set_savepath可以在程序里自由配置session的后台方式。

session_cache_expire与session_cache_limiter函数是配置session缓存时间与头信息的,比如private,public,nocache

与ini_set函数类似

都要在session_start()之前调用

session.save_handler = files
session.save_path = "E:/wamp/tmp/test"

session.save_handler = memcache
session.save_path = "tcp://192.168.1.188:11211"

switch($session->save_handler){
    case 'memcache':
    session_module_name('memcache');
    session_save_path($session->save_path);
        //自定义的时候
    //SessionMemcache::init($session->save_path);
    break;
  case 'files':
    if($session->save_path){
        if(!file_exists($session->save_path)){
        mkdir($session->save_path, true);
        if(!file_exists($session->save_path){
                   exit('session_path is not exits');
               }
        }
        session_module_name('files');
        session_save_path($session->save_path);
    }
    break;
default:
    break;                
}

由于php的session扩展没有json的序列化方式,即使memcached有也不能实现session数据的json化。

使用session_set_save_handler可以在write里改写,但是这里的输入参数已经是序列化后的,所以要自己分解。

 只要session_start()执行就会按照open,read,PHP的其他输出,write,close的顺序执行。

因为会话数据是被序列化的, resource 变量不能被存储在会话中.

序列化句柄 (phpphp_binary) 会受到 register_globals 的限制. 而且,数字索引或者字符串索引包含的特殊字符(|!) 不能被使用. 使用这些字符将脚本执行关闭时的最后出现错误. php_serialize 没有这样的限制.php_serialize 从 PHP 5.5.4 以后可用. 

我还想半天session的反序列化,完美的方法不太好处理,这里限制session的所有键值都避免使用} | ;等敏感字符,没有经过完全测试,可能在复杂结构下会有问题,执行比原生的速度慢,而且随着数据量效率更差。

解决这个问题还是要从C扩展实现,不过临时的解决方案可以尝试一下。

class SessionMemcache{
    private static $_client = null;
    private static $_config = null;
    private static $_expire = 1800;
    private static $is_json = false;
    
    /**
     * 构造函数
     * @param unknown $session
     */
    private function __construct(){
       session_set_save_handler(
            array($this, 'open'),
            array($this, 'close'),
            array($this, 'read'),
            array($this, 'write'),
            array($this, 'destroy'),
            array($this, 'gc')
        );
    } 
    
    public static function init($configArray, $expire, $is_json = false){
        if(self::$_client == null){
            new self();
            self::$_config = $configArray;
            self::$_expire = $expire;
            self::$is_json = $is_json;
        }
        //register_shutdown_function('session_write_close');
    }
    
    /**
     * 打开session连接
     * @return boolean
     */
    public function open($savePath, $sessionName){
        self::$_client = Bootstrap::memFaction(self::$_config);
        return true;
    }
    
    /**
     * 关闭session连接
     * @return boolean
     */
    public function close(){
        return true;
    }
    
    /**
     * 读取session数据
     * @param unknown $id
     * @return Ambigous <NULL, unknown>
     */
    public function read($id){
        $data = self::$_client->get($id);
        if(strlen($data) > 0 && self::$is_json){
            $data = $this->session_json_decode(json_decode($data,true));
        }
        return ($data === false ? null : $data);
    }
    
    /**
     * 保存session数据
     * @param unknown $id
     * @param unknown $value
     */
    public function write($id, $value)
    {
        // $x = file_get_contents(ROOT_PATH . '/temp/sess.txt');
        // file_put_contents(ROOT_PATH . '/temp/sess.txt', sprintf("%s
%s", $x, $value));
        //file_put_contents("D:/aa.txt", var_export($value,true));
        if(self::$is_json){
            $value = $this->session_json_encode($value);
        }
        //file_put_contents("D:/bb.txt", var_export($value,true));
        if (extension_loaded('memcached')) {
            $flag = self::$_client->set($id, $value, self::$_expire);
        } else {
            $flag = self::$_client->set($id, $value, 0, self::$_expire);
        }
        return $flag;
    }
    
    public function destroy($id)
    {

        return self::$_client->delete($id);

    }
    
    public function gc($maxLifetime)
    {

        return true;

    }
    
    protected function session_json_encode($value)
    {
        //按;XXX|切分字符串,对第一个和最后一个做特殊处理
        preg_match_all('/[};](w+)|/',$value,$matchs);//var_dump($matchs);exit;
        $serializeStr = "a:" . (count($matchs[0])+1) .":{";
        $str_copy = $value;
        foreach($matchs[0] as $k => $v){
            $strBefore = strstr($str_copy,$v,true);
            $strAfter = strstr($str_copy,$v);
            $str_copy = substr($strAfter,strlen($v));

            if($k == 0){
                $strOneBefore = strstr($strBefore,'|',true);
                $strOneAfter = strstr($strBefore,'|');
                $strOneAfter = substr($strOneAfter,1);
                if($v[0] == '}'){
                    $serializeStr .= 's:' . strlen($strOneBefore) . ':"' .$strOneBefore . '";' . $strOneAfter . '}';
                }else{
                    $serializeStr .= 's:' . strlen($strOneBefore) . ':"' .$strOneBefore . '";' . $strOneAfter . ';';
                }
            }else{
                if($v[0] == '}'){
                    $serializeStr .= "s:" . strlen($matchs[1][$k-1]) . ':"' . $matchs[1][$k-1] . '";' . $strBefore .  '}';
                }else{
                    $serializeStr .= "s:" . strlen($matchs[1][$k-1]) . ':"' . $matchs[1][$k-1] . '";' . $strBefore .  ';';
                }
            }
            if(!isset($matchs[0][$k+1])){
                $serializeStr .= "s:" . strlen($matchs[1][$k]) . ':"' . $matchs[1][$k] . '";' . substr($strAfter,strlen($v)) .  '}';
            }
            //$delimit[]=$strBefore;
        }
        //$delimit[] = substr($strAfter,strlen($v));
        //var_dump($delimit);exit;
        //var_dump(unserialize($serializeStr));exit;
        //echo $serializeStr;exit;
        return json_encode(unserialize($serializeStr));
    }
    
    function session_json_decode(array $data){
        $ree = '';
        foreach($data as $k => $v){
            if(is_array($v)){
                $ree .= $k . '|' . serialize($v);
            }
            elseif(is_string($v)){
                $ree .= $k . '|s:' . strlen($k) . ':"' . $v . '";';
            }
            elseif(is_int($v)){
                $ree .= $k . '|i:' . $v . ';';
            }
            elseif(is_float($v)){
                $ree .= $k . '|d:' . $v . ';';
            }
            elseif(is_double($v)){
                $ree .= $k . '|d:' . $v . ';';
            }
        }
        return $ree;
    }
}

发表回复

您的电子邮箱地址不会被公开。