8.3 Session的应用
本节介绍Session的工作原理以及在PHP中实现Session编程。
8.3.1 Session的工作原理
Session可以实现客户端和Web服务器的会话,Session数据也以“键—值”对的形式存储在文件中。与Cookie不同,Session数据保存在服务器上。在会话存续期间,Web服务器上的各页面都可以获取 Session 数据,从而了解与客户端沟通的历史记录,避免用户在浏览不同页面时重复输入数据(如重复登录)。
每个 Web 站点都同时与多个用户进行会话,那么 Web 站点又是如何区分与它会话的用户呢?它会给每个访问者分配一个会话ID(SID,session_id)。用户第1次访问Web站点时会得到Web服务器分配的会话ID,以后每次浏览器提交请求都会带上这个会话ID,所有Session数据都与会话ID相关联。Session的工作原理如图8-8所示。
图8-8 Session的工作原理
Session数据保存在服务器端,因此即使浏览器意外关闭,服务器端的Session数据也不会马上被释放。只要有SID,就可以获取对应的Session数据。Session数据也有一个有效期,一旦超过规定的时间没有客户端请求,这个Session数据就会被清除。
下面介绍Session编程的具体方法,图8-8演示的是在用户身份验证时使用Session技术的过程将在第11章结合二手交易市场系统介绍。
8.3.2 开始会话
在PHP脚本中,可以使用session_start()函数开始会话,语法如下:
bool session_start(void)
如果成功开始了会话,则函数返回True;否则返回False。
session_start()函数会为该会话随机生成一个Session ID。可以使用session_id()函数获取或设置Session ID,语法如下:
string session_id([string $id] )
如果使用参数$id,则将其设置为Session ID;否则直接返回当前的Session ID。Session ID用于标识一个Session。
除了Session ID,Session还有一个名字,可以使用session_name()函数获取或设置Session的名字,语法如下:
string session_name([string $name] )
如果使用参数$name,则将其设置为Session的名字;否则直接返回当前的Session名。
【例8-5】 开始会话并输出Session ID和Session的名字,代码如下:
<?php
session_start();
echo("session_id()=" . session_id());
echo("<br>");
echo("session_name()=" . session_name());
?>
输出结果如下:
session_id()=kofmo9l06ka2kuv5jpjth95797
session_name()=PHPSESSID
8.3.3 全局数组$_SESSION
可以使用全局数组$_SESSION设置和获取Session数据,它的用法与普通数组相同,只是数组$_SESSION 由系统定义,可以在程序的任何位置访问它。在访问数组$_SESSION 之前,应该调用session_start()函数开始会话。
【例8-6】 使用全局数组$_SESSION存取Session数据的例子。
<?php
date_default_timezone_set('Asia/Chongqing'); //系统时间差8小时问题
//开始会话
session_start();
if($_SESSION["last_visit"]) {
echo "您上次访问的时间为: ";
echo date("Y-m-d , H:i:s", $_SESSION["last_visit"]);
echo "<br>";
echo "访问次数: ".$_SESSION["num_visits"];
}
else
echo "这是您的第1次访问。";
$_SESSION["last_visit"] = time();
$_SESSION["num_visits"]++;
?>
程序中定义了2个 Session 变量,$_SESSION["last_visit"]用于保存上次访问网页的时间,$_SESSION["num_visits"]用于保存访问网页的次数。
程序中调用 time()函数获取当前的系统时间戳,并保存为$_SESSION["last_visit"]。在获取时间戳之前需要调用 date_default_timezone_set()函数设置时区为“Asia/Chongqing”,否则获取的时间与实际时间会相差8小时。
date()函数用于格式化一个本地时间,即按指定格式返回时间字符串,其语法如下:
string date(string $format [, int $timestamp] )
函数会根据时间戳$timestamp返回时间字符串。参数$format指定返回时间字符串的格式,常用的格式字符如表8-1所示。
表8-1 参数$format中常用的格式字符
每次访问网页时,程序都会获取Session数据并显示在网页中,最后为Session数据设置新值。第1次访问该网页时的界面如图8-9所示。
图8-9 第1次访问例8-6网页时的界面
第2次及以后访问该网页时的界面大致如图8-10所示。
图8-10 第2次访及以后访问例8-6网页时的界面
在不关闭浏览器的情况下,访问其他网站然后再返回,Session数据会保留。而一旦关闭浏览器,Session数据就丢失了。
8.3.4 删除会话变量
对于不需要保留的会话变量,可以调用 unset()函数将其删除,释放占用的内存空间。unset()函数的语法如下:
void unset( mixed $var [, mixed $var[, $... ]] )
可以看到,unset()函数可以同时释放多个变量。
unset()函数不仅可以释放会话变量,也可以用来释放普通变量。
【例8-7】 使用unset()函数释放普通变量的例子。
<?php
$str = "欢迎使用PHP!";
$a= 10;
unset($str, $a);
var_dump($str);
var_dump($a);
?>
以脚本运行的结果如下:
PHP Notice: Undefined variable: str in C:\workspace\test\hello.php on line 6
PHP Stack trace:
PHP 1. {main}() C:\workspace\test\hello.php:0
PHP Notice: Undefined variable: a in C:\workspace\test\hello.php on line 7
PHP Stack trace:
PHP 1. {main}() C:\workspace\test\hello.php:0
NULL
NULL
结果中提示程序中使用了未定义变量(实际是已经释放),最后输出了2个NULL。
【例8-8】 使用unset()函数释放会话变量的例子。
<?php
//开始会话
session_start();
$_SESSION["num_visits"]++;
unset($_SESSION["num_visits"]);
echo($_SESSION["num_visits"]);
?>
以脚本运行的结果如下:
PHP Notice: Undefined index: num_visits in C:\workspace\test\hello.php on line 7
PHP Stack trace:
PHP 1. {main}() C:\workspace\test\hello.php:0
8.3.5 销毁会话
尽管超过有效期的Session数据会被自动销毁,但也可以使用PHP提供的系统函数手动销毁会话。
1.session_unset()函数
session_unset()函数的功能是释放所有的Session变量,但不删除session文件以及不释放对应的session ID,其语法如下:
void session_unset ( void)
【例8-9】 使用session_unset()函数销毁会话的例子。
<?php
//开始会话
session_start();
$_SESSION['user'] = 'admin';
session_unset();
echo($_SESSION['user']);
$_SESSION['user'] = 'admin';
?>
程序的运行结果如下:
用户名:
session_id:7u2pv7m6jijlhi4smdte09q2f5
可见,调用session_unset()函数后,Session变量$_SESSION['user']被释放,但session ID并没有被释放。
2.session_destroy()函数
session_destroy()函数的功能是删除当前用户对应的session文件以及释放sessionid,内存中的$_SESSION变量内容依然保留,其语法如下:
bool session_destroy ( void)
【例8-10】 使用session_unset()函数销毁会话的例子。
<?php
//开始会话
session_start();
$_SESSION['user'] = 'admin';
session_destroy();
echo("用户名:" . $_SESSION['user']);
echo("<br> session_id:" . session_id());
?>
程序的运行结果如下:
用户名:admin
session_id:
8.3.6 配置Session
在 php.ini 中有一组关于 Session 的配置项,它们在[session]分组下定义。本小节介绍常用Session配置项的具体含义。
1.session.save_handler
指定存储和检索与会话关联的数据的处理器名字,可选值如下。
• files:默认值,使用文件。
• mm:使用共享内存。
• sqlite:使用SQLite数据库。
• user:使用用户自定义的函数。
2.session.save_path
如果session.save_handler被设置为files,则使用session.save_path设置存储Session文件的目录。
3.session.name
设置Session名,默认值为“PHPSESSID”。
4.session.auto_start
设置在客户访问任何页面时都自动初始化会话,On为开启,Off为禁止,默认为Off。
5.session.gc_maxlifetime
超过此参数所指的秒数后,保存的 Session 数据将被视为垃圾数据并由垃圾回收程序清理。默认值为1440,即24分钟。
6.session.cache_expire
指定会话页面在客户端缓存(cache)中的有效期限,单位为分钟,默认值为180。