CodeIgniter框架源码笔记(10)——SESSION类之用户接口CI_SESSION

来源:互联网 发布:网络流行歌曲2017劲爆 编辑:程序博客网 时间:2024/06/10 07:49

初始化 Session 类:this>load>library(session);使this->session来访问 Session 对象了。
在 CLI 模式下,Session 类将自动关闭。

在 CodeIgniter 之前的版本中,Session 类并没有实现锁机制,这也就意味着, 两个 HTTP 请求可能会同时使用同一个 session 。说的更专业点就是, 请求是非阻塞的。(requests were non-blocking)
在处理 session 时使用非阻塞的请求同样意味着不安全,因为在一个请求中修改 session 数据(或重新生成 Session ID)会对并发的第二个请求造成影响。这是导致很多问题的根源,同时也是为什么 CodeIgniter 3.0 对 Session 类完全重写的原因。

Session 类自带了 4 种不同的驱动(或叫做存储引擎)可供使用:
files/database/redis/memcached。默认情况下,初始化 session 时将使用文件驱动

SESSION实现的类关系图
SESSION实现的类关系图
一、接口:SessionHandlerInterface.php定义了包含6个方法的接口
自定义session驱动见文章《PHP中用户自定义Session处理机制 》

interface SessionHandlerInterface {    public function open($save_path, $name);    public function close();    public function read($session_id);    public function write($session_id, $session_data);    public function destroy($session_id);    public function gc($maxlifetime);}

二、抽像类:CI_Session_driver
抽像类CI_Session_driver定义了session五个接口(除read方法是返回数据外)返回值(成功/失败)的规范
并定义了加锁/解锁方法,在接下来说的CI_Session类中会用到锁

abstract class CI_Session_driver implements SessionHandlerInterface {    protected $_config;    protected $_fingerprint;//保存session文件内容的md5摘要    protected $_lock = FALSE;    protected $_session_id;    //定义SessionHandlerInterface接口方法中返回成功或失败的值    protected $_success, $_failure;    public function __construct(&$params)    {        $this->_config =& $params;        //接口方法中,所有函数需要返回成功或失败。        //PHP7以前的版本用0表示成功,-1表示失败。在PHP7改成了true代表成功,false代表失败。        //如果不注意区分,那么0值在不同版本的意义就截然相反了。        //所以在构造函数中,根据当前php版本,对属性$this->_success, $this->_failure进行了定义。        if (is_php('7'))        {            $this->_success = TRUE;            $this->_failure = FALSE;        }        else        {            $this->_success = 0;            $this->_failure = -1;        }    }    //当调用destory()方法时,清空客户端的cookie    protected function _cookie_destroy()    {        return setcookie(            $this->_config['cookie_name'],            NULL,            1,            $this->_config['cookie_path'],            $this->_config['cookie_domain'],            $this->_config['cookie_secure'],            TRUE        );    }    //session锁机制,给当前请求中的session对像上锁    protected function _get_lock($session_id)    {        $this->_lock = TRUE;        return TRUE;    }    //session锁机制,给当前请求中的session对像解锁    protected function _release_lock()    {        if ($this->_lock)        {            $this->_lock = FALSE;        }        return TRUE;    }}

三、SESSION类,暴露给用户调用的类
config配置
session常见配置参考《PHP.INI配置:Session配置详细说明 》

$config['sess_driver'] = 'files';//驱动类型 $config['sess_cookie_name'] = 'ci_session'; //客户端存储sessionid的cookies键值$config['sess_expiration'] = 7200; //session过期时间$config['sess_save_path'] = NULL;  //存储路径$config['sess_match_ip'] = FALSE;$config['sess_time_to_update'] = 300;$config['sess_regenerate_destroy'] = FALSE;

获取 Session 数据
1、name=_SESSION[‘name’];

2、name=this->session->name;
由__get魔术方法实现

public function __get($key){    //如果请求的KEY存在,则返回    if (isset($_SESSION[$key]))    {        return $_SESSION[$key];    }    //如果是$this->session->session_id,就返回session_id()    elseif ($key === 'session_id')    {        return session_id();    }    return NULL;}

3、name=this->session->userdata(‘name’);//如果访问项不存在,返回 NULL
获取所有已存在的:$this->session->userdata();

public function userdata($key = NULL){    //如果$key存在且命中,则返回值;如果没有命中则返回NULL    if (isset($key))    {        return isset($_SESSION[$key]) ? $_SESSION[$key] : NULL;    }    //如果key为null,同时$_SESSION还没有数据,则返回空数组    elseif (empty($_SESSION))    {        return array();    }    //下面开始处理$key为NULL情况下,函数返回全部$_SESSION的情况    $userdata = array();    //返回值中要排除的两种特殊的数据用到的key,一种是使用一次就失效的flash_key,一种是过期就失效的temp_key    //因为他们都保存在__ci_vars键中,所以__ci_vars本身这个key也要排除    $_exclude = array_merge(        array('__ci_vars'),        $this->get_flash_keys(),        $this->get_temp_keys()    );    //遍历$_SESSION并生成$userdata    foreach (array_keys($_SESSION) as $key)    {        if ( ! in_array($key, $_exclude, TRUE))        {            $userdata[$key] = $_SESSION[$key];        }    }    return $userdata;}

添加 Session 数据

$newdata = array(    'username'  => 'johndoe',    'email'     => 'johndoe@some-site.com',    'logged_in' => TRUE);$this->session->set_userdata($newdata);$this->session->set_userdata('some_name', 'some_value');//set_userdata函数如下:public function set_userdata($data, $value = NULL){    //解析数组方式    if (is_array($data))    {        foreach ($data as $key => &$value)        {            $_SESSION[$key] = $value;        }        return;    }    //解析键值对方式    $_SESSION[$data] = $value;}

删除 Session 数据

unset($_SESSION['some_name']);// or multiple values:unset(    $_SESSION['some_name'],    $_SESSION['another_name']);//or$this->session->unset_userdata('some_name');//unset_userdata实现public function unset_userdata($key){    //数组方式    if (is_array($key))    {        foreach ($key as $k)        {            unset($_SESSION[$k]);        }        return;    }    //单个键    unset($_SESSION[$key]);}

销毁 Session

session_destroy();// or$this->session->sess_destroy();//sess_destroy就是调用原生session_destroy()方法public function sess_destroy(){    session_destroy();}

当 session 已经处理完毕不再需要时, 你还将 session 保持是打开的状态是容易引发低效的。所以,必须当结束当前请求时, 将不再需要的 session 关闭掉。简单来说就是:当不再需要使用某个 session 变量时,就使用 session_write_close() 方法来关闭它。
register_shutdown_function(‘session_write_close’);

0 0
原创粉丝点击