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

初始化 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’);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值