这个函数的作用就是动态的设置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 = ;
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) > && 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\n%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, , 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[])+) .":{";
$str_copy = $value;
foreach($matchs[] as $k => $v){
$strBefore = strstr($str_copy,$v,true);
$strAfter = strstr($str_copy,$v);
$str_copy = substr($strAfter,strlen($v)); if($k == ){
$strOneBefore = strstr($strBefore,'|',true);
$strOneAfter = strstr($strBefore,'|');
$strOneAfter = substr($strOneAfter,);
if($v[] == '}'){
$serializeStr .= 's:' . strlen($strOneBefore) . ':"' .$strOneBefore . '";' . $strOneAfter . '}';
}else{
$serializeStr .= 's:' . strlen($strOneBefore) . ':"' .$strOneBefore . '";' . $strOneAfter . ';';
}
}else{
if($v[] == '}'){
$serializeStr .= "s:" . strlen($matchs[][$k-]) . ':"' . $matchs[][$k-] . '";' . $strBefore . '}';
}else{
$serializeStr .= "s:" . strlen($matchs[][$k-]) . ':"' . $matchs[][$k-] . '";' . $strBefore . ';';
}
}
if(!isset($matchs[][$k+])){
$serializeStr .= "s:" . strlen($matchs[][$k]) . ':"' . $matchs[][$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;
}
}

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

  1. requests接口自动化6-Body里json格式数据形式的post请求:json

    Body里json格式数据形式的post请求:用json传参 fiddler里请求响应内容: 传递的json数据 [{"stepId":"0","ca ...

  2. 函数指针的返回值是指针数组,数组里放的是int;函数指针的返回值是指针数组,数组里放的是int指针

    函数指针的返回值是指针数组,数组里放的是int 函数指针的返回值是指针数组,数组里放的是int指针 #include <stdio.h> #include <stdlib.h> ...

  3. vue :class 可以接收 字符串 数组 和 对象 对象里面的key值 根据true或false 显示不显示

    vue :class 可以接收 字符串 数组 和 对象 对象里面的key值 根据true或false 显示不显示 https://cn.vuejs.org/v2/guide/class-and-sty ...

  4. 【MM系列】在SAP里查看数据的方法

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]在SAP里查看数据的方法   前言部 ...

  5. foreach 里少用&$v

    foreach ( $prize_list as $k => $v ) { $prize_list[$k]['prize_view'] = DB::name('dati_prize_catego ...

  6. Qt的Model/View Framework解析(数据是从真正的“肉(raw)”里取得,Model提供肉,所以读写文件、操作数据库、网络通讯等一系列与数据打交道的工作就在model中做了)

    最近在看Qt的Model/View Framework,在网上搜了搜,好像中文的除了几篇翻译没有什么有价值的文章.E文的除了Qt的官方介绍,其它文章也很少.看到一个老外在blog中写道Model/Vi ...

  7. (六)Net Core项目使用Controller之一 c# log4net 不输出日志 .NET Standard库引用导致的FileNotFoundException探究 获取json串里的某个属性值 common.js 如何调用common.js js 筛选数据 Join 具体用法

    (六)Net Core项目使用Controller之一 一.简介 1.当前最流行的开发模式是前后端分离,Controller作为后端的核心输出,是开发人员使用最多的技术点. 2.个人所在的团队已经选择 ...

  8. MySQLWorkbench里的稀奇事之timestamp的非空默认值

    在创建表时,某字段为非空时间戳,timestamp not null 问题来了,使用workbench建表时,如果值非空,是需要有一个默认值的,不然会报错. 那么,如果是更新时自动填充可以使用DEFA ...

  9. VS里的 代码片段(Code snippet)很有用,制作也很简单

    工欲善其事必先利其器,而 Visual Studio 就是我们的开发利器. 上一篇文章,介绍了一个很棒的快捷键,如果你还没用过这个快捷键,看完之后应该会豁然开朗.如果你已经熟练的应用它,也会温故而知新 ...

随机推荐

  1. CSS 的overflow:hidden 属性详细解释

    overflow:hidden这个CSS样式是大家常用到的CSS样式,但是大多数人对这个样式的理解仅仅局限于隐藏溢出, 而对于清除浮动这个含义不是很了解.一提到清除浮动,我们就会想到另外一个CSS样式 ...

  2. redis rdb

    http://blog.chinaunix.net/uid-1757778-id-3977331.html

  3. ***PHP implode() 函数,将数组合并为字符串;explode() 函数,把字符串打散为数组

    实例 把数组元素组合为字符串: <?php $arr = array('Hello','World!','I','love','Shanghai!'); echo implode(" ...

  4. 14个Xcode中常用的快捷键操作

    在Xcode 6中有许多快捷键的设定可以使得你的编程工作更为高效,对于在代码文件中快速导航.定位Bug以及新增应用特性都是极有效的. 当然,你戳进这篇文章的目的也在于想要快速的对代码文件进行操作,或者 ...

  5. POJ 3177 Redundant Paths(Tarjan)

    题目链接 题意 : 一个无向连通图,最少添加几条边使其成为一个边连通分量 . 思路 :先用Tarjan缩点,缩点之后的图一定是一棵树,边连通度为1.然后找到所有叶子节点,即度数为1的节点的个数leaf ...

  6. (转载)C++ ofstream和ifstream详细用法

    原文出自[比特网],转载请保留原文链接:http://soft.chinabyte.com/database/460/11433960.sh [导读] ofstream是从内存到硬盘,ifstream ...

  7. MMU和TLB

    MMU和TLB 记得那家芯片公司给我电话面试的时候,别的都还好,可是他问我什么是MMU,我只能干瞪眼.今天在看<Linux内核源码(陈莉君)>的时候,无意中看到第二章内存地址这一节,学习如 ...

  8. wordpress学习一: 环境搭建

    原来想单独找个linux的机器搞套完整的环境,机器都找好了,环境搞了半天.搞完后,感觉环境什么的不重要,核心是学好php和wordpress,单独的环境维护还开发成本都不小,所以 还是采用 xampp ...

  9. 爬虫Larbin解析(二)——sequencer()

    分析的函数: void sequencer() //位置:larbin-2.6.3/src/fetch/sequencer.ccvoid sequencer() { bool testPriority ...

  10. Uubuntu 14.04 LTS反编译apk

    使用apktool反编译apk 1.安装apktool apktool是Google提供的APK编译工具,能够反编译及回编译apk,需要Java环境的支持(在此不再赘述Java的安装与配置,详见< ...