来自:http://www.coolcode.cn/?p=43 " A- u* e7 y& f" p% H( [
默认情况下,PHP会话(session)是通过文件来保存的。这样做有以下几个缺点:
; a+ I$ i8 Q+ }3 i& b y$ `( P: f* W! C. b
会话文件一般都很小,但文件数却很多,在文件系统中保存许多这样的小文件非常浪费空间,且效率不高。
- J' b! \$ J! b" u4 E9 x, ?6 O# U2 E
* G+ l3 T0 D4 t分布式的站点难以利用会话文件来共享会话。 # h8 H9 V8 V9 a) w
会话文件方式不利于统计在线用户的会话信息。
; c4 h* Q8 a c( l6 O( d% g. \/ R" J; |1 H- l
为解决以上问题,我们可以考虑用数据库来保存会话信息。 1 D5 G4 j6 b/ A, p9 L& W% k6 E
( z, O' w& j: S
对于 PHP 开发来说,保存会话用 MySQL 是一个非常不错的选择。MySQL 提供一种建立在内存中的表类型 Heap,如果每条会话数据量很小的话,可以考虑用这种类型的表来进一步优化性能。但是 Heap 类型的表有许多限制,例如它不支持 text 类型的字段,因此如果在无法预测会话数据记录长度的情况下,选择 MyISAM 是比较合适的,这种类型的表没有事物处理开销,对于基于磁盘的表可以得到最优性能。
! I: |; B0 t# _# B4 o9 M, C g3 j, {- j8 P0 ~
下面是 sessions 表的结构:
9 A8 Y4 Y6 Q% W8 GDROP TABLE IF EXISTS `sessions`;
2 U. F$ R' t: m' M* S/ s: HCREATE TABLE `sessions` ( % l2 }9 q1 N' }. e
`session_id` varchar(32) NOT NULL default '', & W Q) W) Z0 d1 H! _7 z! }$ V
`user_id` int(10) unsigned NOT NULL default '0',
" R2 p% h" v! k" h/ Q1 \3 G1 N4 d `data_value` text NOT NULL, $ w3 I+ |* Z2 B( q; U( j' M
`last_visit` timestamp(14) NOT NULL,
; |; V! X" `' L* E4 [ PRIMARY KEY (`session_id`),
" b' M/ y% G" g8 x; T& m8 ` KEY `user_id` (`user_id`) ) W2 ~+ x' h6 ?
) TYPE=MyISAM; 9 G( l" B7 ^- q' K7 y3 Z1 R% n+ s
3 j3 Y7 l( n$ ~6 GPHP 支持用户会话模块,可以通过 session_set_save_handler 来设置自定义的会话处理函数。因为默认的处理模块是 files,因此要在用 session_set_save_handler 设置会话处理函数之前,先用 session_module_name(’user’) 来告诉 PHP 使用用户会话模块, 而session_set_save_handler 必须要在 session_start 之前执行。 1 I1 X5 W3 D& [, u
1 j5 M, p* W/ T; n' j! v; `; s用户会话数据在会话处理函数中都是序列化之后的,要取出其中的某个会话变量,可以对其进行反序列化,默认是 php 序列化方式,可以用 unserialize 函数来反序列化。 ) J6 x( D0 r+ R- X/ W8 T- O/ k" [
/ S! ~( A$ ?) P, [* ~1 o/ Y t下面的代码定义了一个用 MySQL 来处理 PHP 会话的类,其中所使用的 class_mysql.php 请参见 《超级简单但超级实用的 PHP 的 mysql 类》 。 6 Z1 t* L% }7 B1 f' R8 Q
<?php
3 Z6 y. H( b. X# A% d: I6 C/** E$ G7 h% q+ O1 \7 e
* @author Ma Bingyao ) A6 |% p" F8 h+ e- ~% e
* @copyright (C) 2005 CoolCode.CN . Y+ Y. ^) k( J, s; D* t( }
*/ % @& U# Z' i6 s* O2 i7 |3 H9 _
/ @; ]0 W+ e) o4 C5 I/ v
require_once("class_mysql.php");
% f6 J6 \& u/ J' [3 o , a/ \4 Z$ e4 O# Y
class session {
; k( w c7 P* U. P' `1 h9 ? var $db; 7 U! K( b: Q2 |2 g8 h* o" d- D0 x, g
function session(&$db) {
n' ~$ h# P% |8 ^) g $this->db = &$db;
% Y/ m n$ k @! [ session_module_name('user'); " s, i3 H$ e; V) N! v
session_set_save_handler( & r* f, H1 u0 ?
array(&$this, 'open'),
# \, @5 ~, j8 S! Q3 v, B array(&$this, 'close'),
: T$ Q) {5 w; T8 O* L6 i. h array(&$this, 'read'),
" D9 E9 S2 ~3 w: W+ A! D8 g) e8 ]* e array(&$this, 'write'), , S" z1 w/ b/ z7 T( ~( K# @1 y
array(&$this, 'destroy'), * v r2 |: k% o8 ?
array(&$this, 'gc') 1 o4 @. m) a* a, R8 X
);
; O. T7 K" z4 O* w3 b) B session_start();
9 f! X( ]" B/ }; u* J }
1 \* z2 n# E) f function open($path, $name) { D+ {7 U0 `4 j! o# M
return true;
& Q' G0 B& H7 f! p3 P; z! s8 f }
# V& ]8 }7 \* N, C) q2 u function close() {
4 A3 m( E. C5 k) J) n$ B0 @ return true;
) g! s `: w: O5 D$ H } + l l5 R- K! p1 ]0 D
function read($session_id) { : B& g/ { d2 Q) E# K
$session_id = $this->db->escape_string($session_id); , `5 C( Q( R, T3 }" R8 g
if ($row = $this->db->query("select * from `sessions` where `session_id` = '$session_id' limit 1")) {
$ e) o# B/ a. a; R9 {8 } return $row->data_value; + k$ ~; n8 |; Q8 }
}
) B0 _) S/ c6 t' H! I* k& o else { ; C, O8 `, F1 [4 h; }6 q
$this->db->query("insert into `sessions` set `session_id` = '$session_id'");
& s# Q M, @5 [9 T9 J return "";
8 ? a* H+ y: j# \/ l } 1 [5 T8 P- C. y, r; r1 d+ v# v" P
} 1 @' {8 y: y- s- U7 Y4 ?
function write($session_id, $data_value) { 1 c( L4 ^" s8 B5 b& W
$session_id = $this->db->escape_string($session_id); ) G( J$ {; a' j; T
$data_value = $this->db->escape_string($data_value); ( a/ N. G* W! t+ ~+ w/ W9 E
$data = unserialize($data_value);
4 h) O, H: i; ?* j $this->db->query("update `sessions` set "
; l- g% k5 E, M! z# h4 S . "`user_id` = '{$data['user_id']}', "
0 N2 |' ^! @$ S5 n; j . "`data_value` = '$data_value', " + w) O. x% C9 F' E
. "`last_visit` = null "
" \/ ?. o: j: R! u: X# z: } a8 Z . "where `session_id` = '$session_id'");
# ` p# T! ?2 F, X6 D }; N return true;
4 d0 ~' O, f! G! { } 7 y% M; j# r0 w( ~! D
function destroy($session_id) {
: L& G% y$ E `) Z9 e $session_id = $this->db->escape_string($session_id);
: B, @2 m$ i) g5 o2 B# h8 _ $this->db->query("delete from `sessions` where `session_id` = '$session_id'"); : y' c% V5 h7 ~7 W3 ?! n8 F. G
return true;
3 G' o0 P2 w2 H }
/ J* F1 b+ p( ?: w& e( r. x8 w8 ] function gc($lifetime) {
+ ~. c6 G ?; E+ o x" Z $this->db->query("delete from `sessions` where unix_timestamp(now()) - unix_timestamp(`last_visit`) > $lifetime"); 9 N2 O ]+ h, F
return true;
+ W2 `( N/ R* o% S }
4 L1 j* L* T$ I# G1 v& I- L n& @ function replace($session_id, $data_value) { ) `7 W) p& F) {& }
$session_id = $this->db->escape_string($session_id); 4 m) \9 d2 D: j% i
$data_value = $this->db->escape_string($data_value); / F) i$ x* s7 m/ G# {$ u4 F
$data = unserialize($data_value); ) b+ k" `% }; a/ W
$this->db->query("replace `sessions` set "
: o& [- _. B7 ^ . "`session_id` = '$session_id', " + z' t; R- c, D, _& S
. "`user_id` = '{$data['user_id']}', " ( C5 L9 F. l k6 x+ K3 H
. "`data_value` = '$data_value', " 9 q( J1 E5 N9 X: ]2 R
. "`last_visit` = null");
% S. y: K0 Y! {1 n' G }
5 R7 b, A8 e: q' }+ s9 I: k // get sessions by user_id + O# ?; S& E: o# W
function get($user_id) { , @' |: u$ B+ X% q1 r3 `2 h& E2 }
$user_id = $this->db->escape_string($user_id);
' ?# ?( |$ T+ Z+ m4 D/ S return $this->db->query("select * from `sessions` where `user_id` = '$user_id'"); 4 Q/ J3 I' f6 N7 x. x2 M6 Q1 V
} & W' w; _* B" ~6 D; _3 G
// get sessions list
' E# l" T9 d) t1 J' V function list($page, $rows) { " w2 i$ ?3 g# t
if ($page == 0) { ) I3 O( _( f: y( \2 k9 Z R
return $this->db->query("select * from `sessions` order by `user_id`"); & P& \% q. e j+ P0 k! P8 [; S, \5 U5 O
}
( y9 Z$ ]% G7 [4 r. d" e+ o else { * o& t- V7 U8 e$ y. j7 q% z
$start = ($page - 1) * $rows;
" B0 z4 p% J8 x, z F, S( M! | return $this->db->query("select * from `sessions` order by `user_id` limit $start, $rows");
' |! ^ Q7 n. {3 s } 5 o" y) e" ^1 R9 w- M5 X& N4 i
} 5 D7 A7 i; n" d) M" e
}
% r S3 W4 ]5 J' ?; {; I, h5 } C- L8 B?> # y! y# S0 m; D5 {* C! _$ [
这个类的使用很简单,在原来使用 session_start 的地方,替换成 $session = new session($db) 就可以了。$db 表示 sessions 表所在的数据库。
8 m; Q/ n: G# r: v/ o% c5 D# a T( ^& a, |
另外可以用 get 方法来获取某个用户的所有会话信息,通过 list 方法来得到所有用户会话列表。这样就可以方便的管理用户会话了。 |