会话控制
当输出session_start()的时候session会话控制就开始了,我们浏览网站,服务器是识别不了用户的身份的,所以就有了session来控制。使用session会发给客户端浏览器的一个令牌也就是cookie。当用户在应用程序的 Web 页之间跳转时,因为 cookie 存在浏览器中、每次都带上令牌,而在令牌没有过期之前整个用户会话中一直存在下去。
为什么要把session存入数据库,或者共享?
像那些大网站例如百度、腾讯、当你访问新闻和首页,他的二级域名是不一样的,但是也不可能每个域下都让用户去登录。一影响用户的体验,二我个人觉得非常麻烦。所以就有session的一个共享,就是登录一次,其他页面免登陆。也可以说是单点登录吧。
写入数据库应该算是对session的一个扩展,如果说着个是大流量的网站那么,那么session的回收处理,可能对系统性能造成一定的影响,影响性能的原因之一文件系统,在同一个目录下超过10000个文件时,文件的定位将非常耗时。
如果你是多台服务,PHP默认存储session会话是文件形式,其他服务器是访问不到的。
那把session写入数据库有啥好处呢?
控制一个帐号只能一个人登录 统计在线人数 踢出某个在线用户 多站点共享等等。
那说一下php操作session的一个重要函数session_set_save_handler()
。调用他需要6个参数次序分别为
- 启动会话
- 关闭会话
- 读取会话数据
- 写入会话数据
- 销毁会话数据
- 垃圾回收程序
列子,按照执行顺序排列
$sdbc = NULL;
// ini_set('session.serialize_handler','php_serialize');
//自己指定的用户session_id
session_id("nmfd7cnp6j9iib8lv0fg6bu514");
function open_session() {
global $sdbc;
$sdbc = mysqli_connect ('localhost', 'root', '123456', 'test');
var_dump(1);
return true;
}
function read_session($sid) {
global $sdbc;
var_dump($sid);
var_dump(2);
$q = sprintf('SELECT data FROM sessions WHERE id="%s"', mysqli_real_escape_string($sdbc, $sid));
$r = mysqli_query($sdbc, $q);
if (mysqli_num_rows($r) == 1) {
list($data) = mysqli_fetch_array($r, MYSQLI_NUM);
return $data;
} else {
return '';
}
}
function write_session($sid, $data) {
global $sdbc;
var_dump(3);
var_dump($data);
$q = sprintf('REPLACE INTO sessions (id, data) VALUES ("%s", "%s")', mysqli_real_escape_string($sdbc, $sid), mysqli_real_escape_string($sdbc, $data));
var_dump($q);
$r = mysqli_query($sdbc, $q);
var_dump($r);
return true;
}
//此步骤只有在销毁session的时候执行
function destroy_session($sid) {
global $sdbc;
var_dump(4);
$q = sprintf('DELETE FROM sessions WHERE id="%s"', mysqli_real_escape_string($sdbc, $sid));
$r = mysqli_query($sdbc, $q);
$_SESSION = array();
return true;
}
function clean_session($expire) {
global $sdbc;
var_dump(5);
var_dump($expire);
$q = sprintf('DELETE FROM sessions WHERE DATE_ADD(last_accessed, INTERVAL %d SECOND) < NOW()', (int) $expire);
$r = mysqli_query($sdbc, $q);
file_put_contents('33.txt',$expire);
return true;
}
function close_session() {
global $sdbc;
var_dump(6);
return mysqli_close($sdbc);
}
session_set_save_handler('open_session', 'close_session', 'read_session', 'write_session', 'destroy_session', 'clean_session');
session_start();
$_SESSION['id']=1;
$_SESSION['name']='启东';
var_dump($_SESSION);
然后修改了一下php.ini的配置文件
session.gc_divisor = 1 //初始值为1000
session.gc_maxlifetime = 10 //初始值为1440 为了看执行效果特意修改
下面来看一张图片
这张图片为代码执行后的结果 数字5代表垃圾回收10代表时间。
知道了这些步骤我们可以做很多事情,就像统计用户在线人数等。
在初学PHP的时,曾经说聊天室功能(那时还不知道websocket),现在利用session会话就能实现。
如何实现共享?
用户访问服务器端的时候,会响应发送个cookie,而浏览器会存储个cookie,用来识别你是否访问过这个网站,里面还会存储点信息。这里还涉及到一个cookie域的问题。
这个实现其实很简单,只需要对 COOKIE 的域(domain)进行特殊地设置即可,默认情况下,COOKIE 的域是当前服务器的域名/IP 地址,而域不同的话,各个服务器所设置的 COOKIE 是不能相互访问的。下面是设置的配置项
ini_set('session.use_cookies',1);
ini_set('session.cookie_path','/');
ini_set('session.cookie_domain','');//因为的是本地环境,就没有填写,顶级域
那么说一下存入数据库的session序列化。我知道一共有三种
name|s:2:"tb";
//我并没有找到直接反序列化的函数a:2:{s:2:"id";i:1;s:4:"name";s:7:"启动1";}
//反序列化函数unserialize();方便 ...推荐使用idi:1;names:7:"启动1";
写入数据库是这样。目前没找到更好更方便的反序方案