sesion_set_save_hander 的 理解 步骤

2024-02-24 19:58

本文主要是介绍sesion_set_save_hander 的 理解 步骤,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

session_set_save_hander(open,close,read,write,destory,gc) :  总共有 open,close,read,write,destory,gc 这几个参数,且这几个参数 都是定义的函数名:

列如  

function open($path,$name){}

function close($key){}

function read($key){}

function write($key,$value){}

function destory($key){}

function gc($key){}

注意: 以下说到的$key 指的是 PHPSESSIONID : hiuriq6kmr1mv5vf020djpbu869



方法的参数 是 session_set_save_hande通过php 获取得到的,方法的参数 名字 可以随便起,php获取到的PHPSESSSID 会自动指定到方法的参数上去。

方法体里 就是自己具体的逻辑了。

当你上面的方法体逻辑都写好时,通过session_start()的开启,回去调用上面的 open 方法 red方法 和 gc 方法 ,

1.可以理解成 open 找到session 的临时目录($path),然后通过phpsessionid拼接一个前缀(比如sess_hiuriq6kmr1mv5vf020djpbu869 ,这里的sess_ 就是所指的前缀) 得到 $name(也就是具体的临时文件),然后通过red方法传递一个$key 取到 具体的PHPSESSIONID的值$value,取到之后 由于不知道 当前的session 是否还有效 ,所以这时候启动了 gc 垃圾回收。

通过传递一个$key , 来查询当前时间是否大于设置的有效期时间,大于的话 删除,所以当你点击一个页面是,如果大于有效期的话,就可能把你的session文件删掉,这样的话
你通过前两个步骤取得值,就不能被注册到内存中(也就是没有赋值给全局变量$_SESSION),所以当你在这个时候取$_SESSION 时 可能返回空,因为 这次没有注册到内存中。
2.当此次脚本执行完时(不论当前脚本是否嵌套多少脚本,也就是说执行到脚本的最后一行时),通过调用write($key,$value)当当前的值在写到这个phpsessionid 的文件中去。然后通过close($key) 来关闭当前的session.执行完成。
3.当调用session_write_close ()时 会先 调用write($key,$value) ,在调用close ()
4.当调用session_destory_close()时 先删掉当前 sessionid的值,然后close ()

==========================================

session_start()后 对应的session文件是被锁定的,直到当前脚本结束才会解锁。
在锁定期间,令一个进程访问相同session id 要等文件解锁后session_start()才会开始。
解决办法是在 session 设置好数据后调用 session_write_close() 将数据写入文件并且结束session

例如如下代码

PHP code
<?php
session_name("STEST");
session_id("TESTID");
session_start();
$_SESSION["count"]=0;
session_write_close();
sleep(10);
echo "success";
?>


如果不加入session_write_close();
并发3个进程访问该页面,第一个进程执行10秒 第二个执行20秒 第三个执行30秒。
加入session_write_close()后 
并发3个进程会同时在10秒后执行完成


=======================================



<?php
 class SessionDB {
   private $data=null;
   private $session_id=null;
   private $minutes_to_expire=3600;
   
   public function __construct(){
     global $SESSION;
     
     if (isset($_COOKIE['session_id'])){
       $this->session_id = $_COOKIE['session_id'];
     } else {
       
       $this->session_id = md5(microtime().rand(1,9999999999999999999999999)); // GENERATE A RANDOM ID
       
       setcookie('session_id',$this->session_id);
       
       $sql = "INSERT INTO `tb_session_db` (`session_id`, `updated_on`) VALUES ('{$this->session_id}', NOW())";
       mysql_query($sql);
     }
     
     $sql = "SELECT `value` FROM `tb_session_db` WHERE `session_id`='{$this->session_id}'";
     $query = mysql_query($sql);
     
     $this->data = unserialize(mysql_result($query, 0, 'value'));
     $SESSION = $this->data;
   }
   
   private function expire(){
     $date_to_delete = date("Y-m-d H:i:s", time()-60*$this->minutes_to_expire);
     $sql = "DELETE FROM `tb_session_db` WHERE `update_on` <= '$date_to_delete'";
     mysql_query($sql);
   }
   
   public function __destruct(){
     global $SESSION;
     
     $this->data = serialize($SESSION);
     
     $sql = "UPDATE `tb_session_db` SET `value`='{$this->data}', `updated_on`=NOW() WHERE `session_id`='{$this->session_id}'";
     mysql_query($sql);
     
     $this->expire();
   }
 }
 
/*
TABLE STRUCTURE
 CREATE TABLE IF NOT EXISTS `tb_session_db` (
   `session_id` varchar(32) NOT NULL,
   `value` blob,
   `updated_on` datetime DEFAULT NULL,
   PRIMARY KEY (`session_id`)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
*/
?>

<?php
 require_once('session_db.php');
 
define('MYSQL_HOST','mysql.example.com');
define('MYSQL_USER','.......');
define('MYSQL_PASS','.......');
define('MYSQL_BASE','.......');

mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS) or die('Cannot connect');
mysql_select_db(MYSQL_BASE) or die('Cannot select DB');
mysql_set_charset('utf8_general_ci');

 $SESSION = null;
 global $SESSION;
 $session_db = new SessionDB();
?>

当执行一个程序完成时 ,才会调用 上面类的   __destruct() 的方法 这样好理解 因为这是析构函数,所有程序执行完时才执行(可以理解为 在一个程序的某一行给$_SESSION赋值时,不是赋值后就立即写到文件中,而是在程序执行完时再写入。)


由此,我们可见: 当每个用户访问web, PHP的session初始化函数都会给当前来访用户分配一个唯一的session ID。并且在session生命周期结束的时候,将用户在此周期产生的session数据持久到session文件中。用户再次访问的时候,session初始化函数,又会从session文件中读取session数据,开始新的session生命周期。








这篇关于sesion_set_save_hander 的 理解 步骤的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/743195

相关文章

Window Server2016加入AD域的方法步骤

《WindowServer2016加入AD域的方法步骤》:本文主要介绍WindowServer2016加入AD域的方法步骤,包括配置DNS、检测ping通、更改计算机域、输入账号密码、重启服务... 目录一、 准备条件二、配置ServerB加入ServerA的AD域(test.ly)三、查看加入AD域后的变

Window Server2016 AD域的创建的方法步骤

《WindowServer2016AD域的创建的方法步骤》本文主要介绍了WindowServer2016AD域的创建的方法步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、准备条件二、在ServerA服务器中常见AD域管理器:三、创建AD域,域地址为“test.ly”

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

用Java打造简易计算器的实现步骤

《用Java打造简易计算器的实现步骤》:本文主要介绍如何设计和实现一个简单的Java命令行计算器程序,该程序能够执行基本的数学运算(加、减、乘、除),文中通过代码介绍的非常详细,需要的朋友可以参考... 目录目标:一、项目概述与功能规划二、代码实现步骤三、测试与优化四、总结与收获总结目标:简单计算器,设计

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

使用SpringBoot创建一个RESTful API的详细步骤

《使用SpringBoot创建一个RESTfulAPI的详细步骤》使用Java的SpringBoot创建RESTfulAPI可以满足多种开发场景,它提供了快速开发、易于配置、可扩展、可维护的优点,尤... 目录一、创建 Spring Boot 项目二、创建控制器类(Controller Class)三、运行

python安装完成后可以进行的后续步骤和注意事项小结

《python安装完成后可以进行的后续步骤和注意事项小结》本文详细介绍了安装Python3后的后续步骤,包括验证安装、配置环境、安装包、创建和运行脚本,以及使用虚拟环境,还强调了注意事项,如系统更新、... 目录验证安装配置环境(可选)安装python包创建和运行Python脚本虚拟环境(可选)注意事项安装