TP的session

这里是用 thinkphp 3.2.0 版本的框架来做分析的

TPsession 主要是通过一个 session 函数来操作的,当然也可以使用原生的 $_SESSION 来操作,不过 TP 提供的一些特性就没了。

一些可配置的参数

参数 是否必须 描述
SESSION_OPTIONS session的一些配置参数
SESSION_PREFIX session的前缀
VAR_SESSION_ID sessionID变量
SESSION_TYPE 自定义session存储的类型
SESSION_AUTO_START 是否自动启动session

SESSION_OPTIONS

session 的配置参数,主要有下面几个(一般不建议配置):

参数 否否必须 描述
prefix session前缀
id sessionId
name session名称
path session的保存路径
domain cookie_domain
expire gc_maxlifetime
use_trans_sid use_trans_sid
use_cookies use_cookies
cache_limiter 缓存限制器
cache_expire 缓存的到期时间
type session存储的类型

SESSION_TYPE

3.2.0 的版本中,框架只集成了存储到 DB 的功能,如果要存储到 Redis 或者 Memcache 中,需要自己造轮子。

流程解析

session 方法有两个参数,一个是 $name,是必传的;另一个是 $value,默认为空。

设置模式

$name 是数组时,默认设置模式。

前缀设置

如果配置里有前缀,会使用 C 函数设置 SESSION_PREFIX

<?php
if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']);
sessionID变量

如果设置了 VAR_SESSION_ID,并且请求上也有 VAR_SESSION_ID,那么就使用 session_id 设置。

否则使用配置中的 id。(没理解为什么必须要设置 session id)

<?php
if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){
    session_id($_REQUEST[C('VAR_SESSION_ID')]);
}elseif(isset($name['id'])) {
    session_id($name['id']);
}
模式判断

只有 APP_MODEcommon 时,才能自动启用 session

<?php
if('common' != APP_MODE){ // 其它模式可能不支持
    ini_set('session.auto_start', 0);        array(&$hander,"read"), 
        array(&$hander,"write"), 
        array(&$hander,"destroy"), 
        array(&$hander,"gc")); 
}

关于如何使用 Redis 作为 session 驱动,可以看看我之前的文章,PHP SESSION 自定义会话管理器

启动session

如果配置了默认启动,则会直接启动 session

<?php
if(C('SESSION_AUTO_START'))  session_start();
}
一些参数的设定

因为应用场景的问题,需求比较小,简单介绍。

<?php
if(isset($name['name']))            session_name($name['name']);
if(isset($name['path']))            session_save_path($name['path']);
if(isset($name['domain']))          ini_set('session.cookie_domain', $name['domain']);
if(isset($name['expire']))          ini_set('session.gc_maxlifetime', $name['expire']);
if(isset($name['use_trans_sid']))   ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0);
if(isset($name['use_cookies']))     ini_set('session.use_cookies', $name['use_cookies']?1:0);
if(isset($name['cache_limiter']))   session_cache_limiter($name['cache_limiter']);
if(isset($name['cache_expire']))    session_cache_expire($name['cache_expire']);
设置session驱动

这里有个细节,当 type 是一个命名空间的时候,会直接作为驱动进行设置。

也就是说,如果用户需要自己编写 Redissession 驱动,不需要改动源码就可以完成。

<?php
if(isset($name['type']))            C('SESSION_TYPE',$name['type']);
if(C('SESSION_TYPE')) { // 读取session驱动
    $type   =   C('SESSION_TYPE');
    $class  =   strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower($type));
    $hander =   new $class();
    session_set_save_handler(
        array(&$hander,"open"), 
        array(&$hander,"close"), 
        array(&$hander,"read"), 
        array(&$hander,"write"), 
        array(&$hander,"destroy"), 
        array(&$hander,"gc")); 
}

关于如何使用 Redis 作为 session 驱动,可以看看我之前的文章,PHP SESSION 自定义会话管理器

启动session

如果配置了默认启动,则会直接启动 session

<?php
if(C('SESSION_AUTO_START'))  session_start();

读取模式

如果 $value'',那么就会进行值的读取,但是这里混入了一个不法分子...

神奇的session操作

如果 $name 是以 [ 开头的,那就认为是命令,这个很随意...

<?php
if(0===strpos($name,'[')) { // session 操作
    if('[pause]'==$name){ // 暂停session
        session_write_close();
    }elseif('[start]'==$name){ // 启动session
        session_start();
    }elseif('[destroy]'==$name){ // 销毁session
        $_SESSION =  array();
        session_unset();
        session_destroy();
    }elseif('[regenerate]'==$name){ // 重新生成id
        session_regenerate_id();
    }
}

操作列表如下:

操作 描述
[pause] 暂停session
[start] 启动session
[destroy] 销毁session
[regenerate] 重新生成id
是否存在某个session

如果想要知道某个 session 是否存在,只需要在 key 之前加上 ? 前缀(支持二维数组)。例如:session('?aa')session('?aa.bb')

<?php
if(0===strpos($name,'?')){ // 检查session
    $name   =  substr($name,1);
    if(strpos($name,'.')){ // 支持数组
        list($name1,$name2) =   explode('.',$name);
        return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]);
    }else{
        return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]);
    }
}
清空session

如果需要清空整个 session,只需要将 $name 置为 null 即可(第二个参数必须为 '')。例如:session(null)

<?php
if(is_null($name)){ // 清空session
    if($prefix) {
        unset($_SESSION[$prefix]);
    }else{
        $_SESSION = array();
    }
}
获取session
<?php
if($prefix){ // 获取session
    if(strpos($name,'.')){
        list($name1,$name2) =   explode('.',$name);
        return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null;  
    }else{
        return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null;                
    }            
}else{
    if(strpos($name,'.')){
        list($name1,$name2) =   explode('.',$name);
        return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null;  
    }else{
        return isset($_SESSION[$name])?$_SESSION[$name]:null;
    }            
}

删除模式

如果 $valuenull,则默认删除当前的 $name

<?php
if(is_null($value)){ // 删除session
    if($prefix){
        unset($_SESSION[$prefix][$name]);
    }else{
        unset($_SESSION[$name]);
    }
}

赋值模式

只要上面的都满足,就可以赋值了。

所以啊,如果想要赋值给某个 session 值为 '' 或者 null 的话,可能就不是你想象的那样了。

<?php
if(is_array($name)) {

}elseif('' === $value){ 

}elseif(is_null($value)){ // 删除session

}else{ // 设置session
    if($prefix){
        if (!is_array($_SESSION[$prefix])) {
            $_SESSION[$prefix] = array();
        }
        $_SESSION[$prefix][$name]   =  $value;
    }else{
        $_SESSION[$name]  =  $value;
    }
}

最后

作为一个函数,session 是非常强大了,但是,如果不仔细看一下,踩坑的几率还是非常高的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容