优雅地使用CodeIgniter 3之Session类库(2)
发布于: April 24, 2015, 2:45 pm 分类: Codeigniter 作者: Zigzag
CI3的Session的重大改变就是默认使用了原生的Session,这符合Session类库本来的意思,似乎更加合理一些。总体来说,虽然设计理念不同,但为了保证向后兼容性,类库的使用方法与CI2.0的差别不是很大。一般的使用过程是这样的:
写数据
//直接加载默认的files驱动器 $this->load->library('session'); $this->session->set_userdata('some_name', 'some_value'); //单个数据 $newdata = array( 'username' => 'johndoe', 'email' => 'johndoe@some-site.com', 'logged_in' => TRUE ); $this->session->set_userdata($newdata); // 数组,适合一次保存多个数据的情形。
这跟CI2.0几乎没有区别。接下来看读取Session数据的方法。
读数据
$name = $_SESSION['name']; // 直接使用,似乎是官方推荐的方法 $name = $this->session->name ; //使用魔术方法,session的名称name变成了session对象的一个属性。 $name = $this->session->userdata('name'); //与CI2的使用方法一样,为保持向后兼容性的一种用法
另外一点需要注意,CI3开始,如果返回的数据是空,以前都会置为 FALSE,现在则会 NULL。 所以以前的写法:
$name = $this->session->userdata('name'); if($name === FALSE){ //…… }
需要换成:
$name = $this->session->userdata('name'); if($name === NULL){ //…… }
可以使用以下方法判断是否含有某个名称的session:
if($this->session->has_userdata('some_name')){ } //或者 if(isset($_SESSION['some_name'])){ }
删除数据
删除的话则和以前类似:
unset($_SESSION['some_name']); //或者批量删除 unset( $_SESSION['some_name'], $_SESSION['another_name'] ); //or $this->session->unset_userdata('some_name'); //或者批量删除 $array_items = array('username', 'email'); $this->session->unset_userdata($array_items);
总体上看,CI3的Session类库设计理念是更加接近原生的函数和方法,同时为了保持向后兼容性,原来的方法也尽量保留了下来。于此同时,原来的flash data理念做了新的设计,加入了temp data的概念,那么这两个data有什么区别呢?
flash data 、 temp data 与user data的区别
这三种session数据的名字是CI约定俗成的,指代的内容是不一样的,并不存在包含关系。不要错误地认为user data包含flash data或者temp data。在CI的api设计中,分别应用不同场景:
1. flash data的主要特征是:保存的数据是一次性数据,在下次请求中用过一次就没了。本质上讲,flash data跟普通的session数据无异,CI不过是对该类data的名称做出了特殊标记,保证了它们拥有了只能用一次的特征,所以你可以使用以下方法将普通的user data标记为flash data:
$_SESSION['item'] = 'value'; //先有一个session $this->session->mark_as_flash('item'); // 单个标记成flash data,item是session的名称 $this->session->mark_as_flash(array('item', 'item2')); //批量标记 //或者一次性的标记,不再是先有session,再标记成flash data的过程 $this->session->set_flashdata('item', 'value');
flash data的适用场景是:将操作结果返回到下一次请求的页面上。比如有个保存操作,提交后会跳转到一个新的页面,你可以使用flash data保存一句话“保存已成功”,该句话只在跳转的页面显示一次,再次刷新跳转页面,就不会显示了。
2. temp data的主要特征是: 保存的数据在规定的时间内有效,它的生命期由方法$this->session->set_tempdata('item', 'value', 300)设置,其中的300意思是该session数据的有效期为5分钟,超过规定时间(即便是session还没过期)就会失效,它的时效性介于flash data 和user data 之间。它和flash data在本质上是类似的,也可以从普通的session转化过来:
$_SESSION['item'] = 'value'; $this->session->mark_as_temp('item', 300); //标记item的生命期只有300s $this->session->mark_as_temp(array('item', 'item2'), 300); //批量将生命期标记为300s //分别标记成不同的生命期 $this->session->mark_as_temp(array( 'item' => 300, 'item2' => 240 )); $this->session->set_tempdata('item', 'value', 300);//直接设置一个temp data,常用方法
temp data的适用场景是:保存一些更加细粒度的、更加隐私的session数据。比如某些令牌token,比较重要,为了安全让它的生命期更短一些,可以保证安全。temp data的设计从某种方面保证了session拥有不同生命期的数据。
3. user data的主要特征是:保存的数据在session有效期内均有效,它的生命期由sess_expiration设置,一般默认是7200s,而且它也是生命期最长的。
flash data 、 temp data 与user data的读取
CI Session类中的flash data、temp data与user data,都能以$_SESSION['item'] 的方式获取到。同时又可使用各自的方法获取到:
echo $_SESSION['item']; //三种类型的数据都能得到 $this->session->flashdata('item'); // 获取flash data $this->session->flashdata(); //获取全部flash data $this->session->tempdata('item'); //获取temp data $this->session->tempdata(); //获取全部temp data $this->session->userdata('item'); // 获取user data $this->session->userdata(); //获取全部user data
但是要注意:这几种数据是分割开来的,不能使用$this->session->userdata('item'),去访问一个设为flash data的数据:
$this->session->set_tempdata('item', 'value', 300); $this->session->userdata('item'); //将会返回null $this->session->set_flashdata('item2', 'value'); $this->session->userdata('item2'); //将会返回null
Session数据的删除与销毁
session数据的删除可以理解为细粒度的删除某个session数据,可以使用:
$this->session->unset_userdata('item'); //删除user data $this->session->unset_tempdata('item'); //删除temp data unset($_SESSION['item']); //对flash、temp、user三种data都有效,原生方法,推荐。
session销毁,则会使所有数据类型失效,包括flash data 和temp data:
session_destroy(); //原生,推荐 // 或者 $this->session->sess_destroy();
扩展内容:flash、temp及user data的设计思路
首先,三种类型的数据必定存在了$_SESSION超级变量中,也就是说使用set_tempdata()和set_flashdata()方法,都会把对应的名称加入到$_SESSION超级变量中。不过这还没完,CI会用一个叫__ci_vars的session数据来区分flash 、temp与user data的不同。
$_SESSION['__ci_vars'] = array();
使用set_flashdata('item', 'value')时,除了$_SESSION['item'] = 'value'; 同时会有:
//还是首先会被保存到超级变量中 $_SESSION['item'] = 'value'; //然后保存到__ci_vars的session中 // session值‘new’是CI自己定义的,没特殊含义,可以看成是flash data的标记 $_SESSION['__ci_vars']['item'] = 'new';
而使用set_tempdata('item2', 'value', 300)时,也是类似,不过略有区别:
//还是首先会被保存到超级变量中 $_SESSION['item2'] = 'value'; //然后保存到__ci_vars的session中 // 13789020340是当前时间戳加上300s, time() + 300; //300来自于过期时间设置,可以在方法中传入 $_SESSION['__ci_vars']['item2'] = 13789020340;
当使用这些不同类型的数据时,CI首先看$_SESSION是否含有这个key,然后会根据$_SESSION['__ci_vars']数据包中key对应的值来判断,简单地说,就是看对应的值是不是int类型。如果是,就认为是temp data;如果不是,则认为是flash data。所以,你可以使用$_SESSION()方法获得所有类型的数据,也可以使用unset方法,删除掉所有类型的数据。
设置完flash data和temp data的下次请求时,构造函数都会判断$_SESSION['__ci_vars']中的特定数据,如果值为‘new’的,则置为‘old’;如果值是数字,则跟当前的时间戳比较,小于的话,则会删除该key下的数据。
再次请求时,flash data中置为‘old’的数据自动被删除,无法再次读取,temp data中的key已经过期删除,取值为NULL。
下一节我们主要讲讲CI2和CI3之间Session类库的区别。