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

相关文章

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

SpringBoot路径映射配置的实现步骤

《SpringBoot路径映射配置的实现步骤》本文介绍了如何在SpringBoot项目中配置路径映射,使得除static目录外的资源可被访问,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一... 目录SpringBoot路径映射补:springboot 配置虚拟路径映射 @RequestMapp

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

Linux搭建ftp服务器的步骤

《Linux搭建ftp服务器的步骤》本文给大家分享Linux搭建ftp服务器的步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录ftp搭建1:下载vsftpd工具2:下载客户端工具3:进入配置文件目录vsftpd.conf配置文件4:

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

MySQL设置密码复杂度策略的完整步骤(附代码示例)

《MySQL设置密码复杂度策略的完整步骤(附代码示例)》MySQL密码策略还可能包括密码复杂度的检查,如是否要求密码包含大写字母、小写字母、数字和特殊字符等,:本文主要介绍MySQL设置密码复杂度... 目录前言1. 使用 validate_password 插件1.1 启用 validate_passwo

springboot整合mqtt的步骤示例详解

《springboot整合mqtt的步骤示例详解》MQTT(MessageQueuingTelemetryTransport)是一种轻量级的消息传输协议,适用于物联网设备之间的通信,本文介绍Sprin... 目录1、引入依赖包2、yml配置3、创建配置4、自定义注解6、使用示例使用场景:mqtt可用于消息发

Java实现TXT文件导入功能的详细步骤

《Java实现TXT文件导入功能的详细步骤》在实际开发中,很多应用场景需要将用户上传的TXT文件进行解析,并将文件中的数据导入到数据库或其他存储系统中,本文将演示如何用Java实现一个基本的TXT文件... 目录前言1. 项目需求分析2. 示例文件格式3. 实现步骤3.1. 准备数据库(假设使用 mysql

MySQL进行分片合并的实现步骤

《MySQL进行分片合并的实现步骤》分片合并是指在分布式数据库系统中,将不同分片上的查询结果进行整合,以获得完整的查询结果,下面就来具体介绍一下,感兴趣的可以了解一下... 目录环境准备项目依赖数据源配置分片上下文分片查询和合并代码实现1. 查询单条记录2. 跨分片查询和合并测试结论分片合并(Shardin

MySQL配置多主复制的实现步骤

《MySQL配置多主复制的实现步骤》多主复制是一种允许多个MySQL服务器同时接受写操作的复制方式,本文就来介绍一下MySQL配置多主复制的实现步骤,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 环境准备2. 配置每台服务器2.1 修改每台服务器的配置文件3. 安装和配置插件4. 启动组复制4.