用数据库管理PHP会话
<?php
/*
// =======================================
用数据库来管理会话的最大动机:
通过部署多个Web服务器,可以平衡HTTP负载并利用数据库服务器,也可以解决服务器的性能瓶颈问题。
// =======================================
*/
/*
// 会话表结构
// 有一个附加的索引,它允许使用后面描述的自定义垃圾收集代码快速删除未使用的会话。
create talbe phpsession(
session_id varchar(50) not null,
session_variable text,
last_accessed decimal(15,3) not null,
primary key(session_id),
key last_acc (last_acessed)
)
*/
function getMicroTime(){
// microtime()返回自格林威治时间
// 1970年1月1日0:00:00起计算的秒数
// 作为微秒部分和一个秒部分
// 例如: 0.08344800 100952237
// 将这两部分转换到一个数组中
$mtime = explode(" ", microtime());
// 返回这两部分之和
// 例如: 100952237.08344800
return($mtime[1]+$mtime[0]);
}
/*
// 每当初试化一个会话时由PHP调用会话打开处理器
// 总是返回true
*/
function sessionOpen($database_name, $table_name){
// 数据库连接
// $connection
// 保存表名称的全局变量
// $session_table
// 将数据库名保存在一个全局变量中
global $connection;
global $hostname;
global $username;
global $password;
if(!($connection = @mysql_connect($hostname, $username, $password))){
showerror();
}
if(!mysql_select_db($database_name, $connection)){
showerror();
}
// 将表名保存在一个全局变量中
global $session_table;
$session_table = $table_name;
return true;
}
/*
// 每当调用session_start()和读会话变量时
// 调用该函数
// 当会话不存在时返回""
// 当会话存在时返回(串行化的)字符串
*/
function sessionRead($sess_id){
// 访问DBMS连接
global $connection;
// 访问保存表名称的全局变量
// 该表保存会话变量
global $session_table;
// 组织一个查询以找到由$session_id识别的会话
$search_query = "SELECT * FROM $sesson_table WHERE session_id= '$sess_id'";
// 执行查询
if(!($result = @mysql_query($search_query, $connection))){
showerror();
}
if(mysql_num_rows($result) == 0){
// 没有找到会话,返回一个空字符串
return '';
}else{
// 找到一个会话,返回串行字符串
$row = mysql_fetch_array($result);
return $row["session_variable"];
}
}
/*
// 当利用session_start()调用初试化一个会话时,
// 当注册或注销变量时和当修改会话变量时,
// 调用该函数。成功则返回true
*/
function sessionWrite($sess_id,$val){
global $connection;
global $session_table;
$time_stamp = getMicroTime();
$search_query = "SELECT session_id FROM $session_table
WHERE session_id = '$sess_id'";
// 执行查询
if(!($result = @mysql_query($search_query, $connection))){
showerror();
}
if(mysql_num_rows($result) == 0){
// 没有找到会话,则插入一个新的会话
$insert_query =
"INSERT INTO $session_table
(session_id, session_variable, last_accessed)
VALUES ('$sess_id', '$val', $time_stamp)";
if(!($result = @mysql_query($insert_query, $connection))){
showerror();
}
}else{
// 找到存在的会话,更新会话变量
$update_query = "
UPDATE $session_table
SET session_variable = '$val',
last_accessed = $time_stamp
WHERE session_id = '$sess_id'";
//
if(!($result = @mysql_query($update_query, $connection))){
showerror();
}
}
return true;
}
/*
// 在关闭会话时执行函数
// 总是返回true
*/
function sessionClose(){
return true;
}
/*
// 每当发出session_destroy()函数调用时
// 就会调用该函数。如果会话已经成功地删除则返回true
*/
function sessionDestroy($sess_id){
global $connection;
global $session_table;
$delete_query = "
DELETE FROM $session_table
WHERE session_id = '$sess_id'";
if(!($result = @mysql_query($update_query, $connection))){
showerror();
}
return true;
}
/*
// 垃圾收集处理器
// 利用session.gc_probability中指定的可能性
// 在会话开始时调用该函数
// 通过删除所有已经有最后$max_lifetime秒未使用的
// 会话来执行垃圾收集,其中$max_lifetime在
// session.gc_maxlifetime中设置
// 如果DELELTE查询成功则返回true
*/
function sessionGC($max_lifetime){
global $connection;
global $session_table;
$time_stamp = getMicroTime();
$delete_query = "
DELETE FROM $session_table
WHERE last_accessed < ($time_stamp - $max_lifetime)";
if(!($result = @mysql_query($delete_query, $connection))){
showerror();
}
return true;
}
?>
利用PHP来注册用户定义的会话处理器
<?php
// 调用来注册用户回调函数
session_set_save_handler (
"sessionOpen",
"sessionClose",
"sessionRead",
"sessionWrite",
"sessionDestroy",
"sessionGC");
?>