PHP SESSION 的工作原理

在客户端(如浏览器)登录网站时,被访问的 PHP 页面可以使用 session_start() 打开 SESSION,这样就会产生客户端的唯一标识 SESSION ID(此 ID 可通过函数 session_id() 获取/设置)。

SESSION ID 可以通过两种方式保留在客户端,使得请求不同的页面时,PHP 程序可以获知客户端的 SESSION ID;一种是将 SESSION ID 自动加入到 GET 的 URL 中(这个只能在unix系统下能实现,windows系统不能实现自动加入url中),或者 POST 的表单中,默认情况下,变量名为 PHPSESSID;另一种是通过 COOKIE,将 SESSION ID 保存在 COOKIE 中,默认情况下,这个 COOKIE 的名字为 PHPSESSID。不管哪一种方式,这个标识符是唯一的,php就凭着这个标识符来读写SESSION数据。

SESSION 的数据保存在服务器端,但不是保存在内存中,而是保存在文件或数据库中。默认情况下,php.ini 中设置的 SESSION 保存方式是files(session.save_handler = files)。这是可以更改的,是用数据库,redis,memcache都可以。

更改存储方式

  • 修改php.ini的设置(修改后重启)
session.save_handler = redis
  • ini_set
ini_set(“session.save_handler”,”redis”);
  • session_module_name
  session_module_name("files");  // ASCII files
session_module_name("mm"); // Shared memory
session_module_name("user"); // Custom session backend
实现数据库存储
  • 更改方式
session_module_name("user");
  • 建立数据库表

id就是唯一标识符,data就是数据,还可以自定义其他的内容例如过期日期等

CREATE TABLE 'session'(
'id' CHAR(30) NOT NULL,'data' CHAR(3000),
PARMIRY BY ('id')
);
  • 读写代码

实际读写代码,并用session_set_save_handler注册

session_set_save_handler (
callable $open ,
callable $close ,
callable $read ,
callable $write ,
callable $destroy ,
callable $gc
[, callable $create_sid ] );

如果用对象的方式,还需要注意处理

在脚本执行完毕之后,PHP 内部会清除对象, 所以有可能不调用 write 和 close 回调函数。 这样可能会引发非预期的行为,所以当使用对象作为会话保存管理器时, 需要通过注册 shutdown 回调函数来规避风险。 通常,你可以通过调用 register_shutdown_function() 函数 来注册 'session_write_close' 回调函数。

在 PHP 5.4.0 中,可以调用 session_register_shutdown() 函数来注册 shutdown 回调函数。 如果你使用session_set_save_handler() 的 OOP 原型, 那么仅需设置 “register shutdown” 为 TRUE 即可。

简单例子

<?php

$con =mysql_connection("127.0.0.1","user" , "pass");
mysql_select_db("session"); function open($save_path, $session_name)
{
return(true);
} function close()
{
return(true);
} function read($id)
{
if($result = mysql_query("SELECT * FROM session WHERE id='$id'"))
{
if($row = mysql_felth_row($result ))
{ return $row["data"]; }
}
else
{
return "";
}
} function write($id, $sess_data)
{
if($result = mysql_query("UPDATE session SET data='$sess_data' WHERE id='$id'"))
{
return true;
}
else
{
return false;
}
} function destroy($id)
{
if($result = mysql_query("DELETE * FROM session WHERE id='$id'"))
{
return true;
}
else
{
return false;
}
} /*********************************************
* WARNING - You will need to implement some *
* sort of garbage collection routine here. *
*********************************************/
function gc($maxlifetime)
{
return true;
} session_set_save_handler("open", "close", "read", "write", "destroy", "gc"); session_start();

 对象的方式

<?php
class FileSessionHandler
{
private $savePath; function open($savePath, $sessionName)
{
$this->savePath = $savePath;
if (!is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
} return true;
} function close()
{
return true;
} function read($id)
{
return (string)@file_get_contents("$this->savePath/sess_$id");
} function write($id, $data)
{
return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
} function destroy($id)
{
$file = "$this->savePath/sess_$id";
if (file_exists($file)) {
unlink($file);
} return true;
} function gc($maxlifetime)
{
foreach (glob("$this->savePath/sess_*") as $file) {
if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
unlink($file);
}
} return true;
}
} $handler = new FileSessionHandler();
session_set_save_handler(
array($handler, 'open'),
array($handler, 'close'),
array($handler, 'read'),
array($handler, 'write'),
array($handler, 'destroy'),
array($handler, 'gc')
); // 下面这行代码可以防止使用对象作为会话保存管理器时可能引发的非预期行为
register_shutdown_function('session_write_close'); session_start();

新接口( PHP 5.4 开始)

<?php
class MySessionHandler implements SessionHandlerInterface
{
private $savePath; public function open($savePath, $sessionName)
{
$this->savePath = $savePath;
if (!is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
} return true;
} public function close()
{
return true;
} public function read($id)
{
return (string)@file_get_contents("$this->savePath/sess_$id");
} public function write($id, $data)
{
return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
} public function destroy($id)
{
$file = "$this->savePath/sess_$id";
if (file_exists($file)) {
unlink($file);
} return true;
} public function gc($maxlifetime)
{
foreach (glob("$this->savePath/sess_*") as $file) {
if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
unlink($file);
}
} return true;
}
} $handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();

PHP SESSION 保存到数据库的更多相关文章

  1. php将session保存到数据库的类实例(php版本需要大于5.4)

    这里实现了一个把session存储到数据库的类,包括数据表的创建.类的使用.php的配置. 可以更好地进行用户控制管理. 做项目的时候,有一个需求,是要实现禁止一个账号两处登录.同时要统计当前在线用户 ...

  2. ASP.NET将Session保存到数据库中

    因为ASP.NET中Session的存取机制与ASP相同,都是保存在进行中, 一旦进程崩溃,所有Session信息将会丢失,所以我采取了将Session信息保存到SQL Server中,尽管还有其它的 ...

  3. 小技巧-ASP.Net session保存在数据库服务器

    引用博客:http://www.cnblogs.com/lykbk/archive/2013/01/13/hf576856868.html web Form 网页是基于HTTP的,它们没有状态, 这意 ...

  4. Asp.Net将Session保存在数据库中

    1.由于项目dll文件变动比较频繁,而保存登陆的状态又保存在Session中,所以导致用户经常无故掉线.(dll变动的时候导致Session丢失) 2.有一种方法可以长期保存session,那就是se ...

  5. Java Hour 47 WeatherInfo 保存到数据库

    经历了上周简单的休整以后,我们继续Hibernate 之旅. 保存到数据库 private void saveWeatherInfo(Weatherinfo weatherInfo) { // Sav ...

  6. php将会话保存在数据库里

    php默认把会话保存在临时文件中,保存在数据库中可以提高安全性,在共享主机服务器上,所有web站点都使用同一个临时目录,这意味着数十个程序都在同一位置进行文件读取的操作,我们很容易就编写一个脚本从这个 ...

  7. 进程外Session保存和全局文件错误捕获

    Session深入学习,进程外的Session 当用户登入页面跳转时候,我们会将用户登录信息保存在服务端一个键值对的Session(Session池)中.那么Session池又是在哪里呢? 它最终默认 ...

  8. Java中将图片保存到数据库中

    在实际的开发中,我们可能需要将图片.影音等文件直接保存到数据库中,然后通过编程方式将数据读出进行使用.例如将读出的图片数据显示出来,将读出的电影文件播放出来. 二进制数据直接保存到文件和从文件中读出非 ...

  9. XAF:如何让用户在运行时个性化界面并将个性化信息保存到数据库中 win/web/entityframework/xpo

    本主题介绍如何启用管理模型差异(XAFML),并将设置存储在数据库中.   名词解释: 1.模型:XAF中把所有应用程序的结构都用模型来定义,比如列表,有哪些列,名称是什么,对应的字段名是什么,业务对 ...

随机推荐

  1. 判断Check复选框是否选中

    <div id="prm_div" style="font-size: 12px;" align="left"> <for ...

  2. 同时执行2个存储过程,2个SP中分别有相同的临时表名,会有冲突吗?

    同时执行2个存储过程,2个SP中分别有相同的临时表名,会有冲突吗?答案:不会 这就可以在以后写存储过程的时候统一临时表名了. alter procedure sp_01 as begin create ...

  3. Gearman 安装使用教程

    Gearman是一个分发任务的程序框架,可以用在各种场合,Gearman更偏向于任务分发功能.它的任务分布非常简单,简单得可以只需要用脚本即可完成. Gearman 分布式任务实现原理上只用到2个字段 ...

  4. asp.net实现手机号码归属地查询

    protected void Button1_Click(object sender, EventArgs e)        {            if (Regex.IsMatch(TextB ...

  5. ExtJS 等待两个/多个store加载完再执行操作的方法

    ExtJS是一种主要用于创建前端用户界面,是一个基本与后台技术无关的前端ajax框架. Extjs加载Store是异步加载的,这有很多好处.但是当我们要在两个或多个不同的store加载完再执行一些操作 ...

  6. .net(C#)操作文件的几种方法汇总

    .net(C#)操作文件的几种方法汇总 System.IO命名空间下类的用法:在System.IO名称空间中包含了用于文件输入输出的主要类.File:实用类,提供许多静态方法,用于移动.复制和删除文件 ...

  7. wire与reg的区别?转载大神!

    本文转自:http://www.cnblogs.com/thymon/archive/2010/06/09/1754541.html //------------------------------- ...

  8. iOS开发HTTPS实现之信任SSL证书和自签名证书

    iOS开发HTTPS实现之信任SSL证书和自签名证书 转自:http://www.jianshu.com/p/6b9c8bd5005a/comments/5539345 (收录一下供自己学习用的) 字 ...

  9. 替换APK中的jar包文件

    [Qboy] 2014年12月21日 这几天,我第一次做的android游戏(WE!青春纪)马上就要上线.上线之前需要把各个渠道的SDK加入到我们游戏中,与渠道进行联运.但是商务很给力,一下子联系了1 ...

  10. adb 连接时 device offline

    继上一篇博文,会发现最后图片上 adb连接时候提示device offline 以下三种方法可以试一下~我是试到最后一种才成功 1.重启手机 2.adb kill-server    adb star ...