使用 MySQL 开始 PHP 会话


Posted in PHP onDecember 21, 2006

默认情况下,PHP会话(session)是通过文件来保存的。这样做有以下几个缺点:

    会话文件一般都很小,但文件数却很多,在文件系统中保存许多这样的小文件非常浪费空间,且效率不高。
    分布式的站点难以利用会话文件来共享会话。
    会话文件方式不利于统计在线用户的会话信息。
    为解决以上问题,我们可以考虑用数据库来保存会话信息。

    对于 PHP 开发来说,保存会话用 MySQL 是一个非常不错的选择。MySQL 提供一种建立在内存中的表类型 Heap,如果每条会话数据量很小的话,可以考虑用这种类型的表来进一步优化性能。但是 Heap 类型的表有许多限制,例如它不支持 text 类型的字段,因此如果在无法预测会话数据记录长度的情况下,选择 MyISAM 是比较合适的,这种类型的表没有事物处理开销,对于基于磁盘的表可以得到最优性能。

    下面是 sessions 表的结构:

    DROP TABLE IF EXISTS `sessions`;
    CREATE TABLE `sessions` (
      `session_id` varchar(32) NOT NULL default '',
      `user_id` int(10) unsigned NOT NULL default '0',
      `data_value` text NOT NULL,
      `last_visit` timestamp(14) NOT NULL,
      PRIMARY KEY (`session_id`),
      KEY `user_id` (`user_id`)
    ) TYPE=MyISAM;
    PHP 支持用户会话模块,可以通过 session_set_save_handler 来设置自定义的会话处理函数。因为默认的处理模块是 files,因此要在用 session_set_save_handler 设置会话处理函数之前,先用 session_module_name('user') 来告诉 PHP 使用用户会话模块, 而session_set_save_handler 必须要在 session_start 之前执行。

    用户会话数据在会话处理函数中都是序列化之后的,要取出其中的某个会话变量,可以对其进行反序列化,默认是 php 序列化方式,可以用 session::unserialize 函数来反序列化。

    下面的代码定义了一个用 MySQL 来处理 PHP 会话的类,其中所使用的 class_mysql.php 请参见 《超级简单但超级实用的 PHP 的 mysql 类》 。

    〈?php
    /**
    * @author 马秉尧
    * @copyright (C) 2005 CoolCode.CN
    */

    require_once(“class_mysql.php“);

    class session {
        var $db;
        function session(&$db) {
            $this-〉db = &$db;
            session_module_name('user');
            session_set_save_handler(
                array(&$this, 'open'),
                array(&$this, 'close'),
                array(&$this, 'read'),
                array(&$this, 'write'),
                array(&$this, 'destroy'),
                array(&$this, 'gc')
            );
            session_start();
        }
        function unserialize($data_value) {
            $vars = preg_split(
                '/([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\|/',
                $data_value, -1, PREG_SPLIT_NO_EMPTY |
                PREG_SPLIT_DELIM_CAPTURE
            );
            for ($i = 0; $vars[$i]; $i++) {
                $result[$vars[$i++]] = unserialize($vars[$i]);
            }
            return $result;
        }
        function open($path, $name) {
            return true;
        }
        function close() {
            return true;
        }
        function read($session_id) {
            $session_id = $this-〉db-〉escape_string($session_id);
            if ($row = $this-〉db-〉query(“select * from `sessions` where `session_id` = '$session_id' limit 1“)) {
                return $row['data_value'];
            }
            else {
                $this-〉db-〉query(“insert into `sessions` set `session_id` = '$session_id'“);
                return ““;
            }
        }
        function write($session_id, $data_value) {
            $data = $this-〉unserialize($data_value);
            $session_id = $this-〉db-〉escape_string($session_id);
            $data_value = $this-〉db-〉escape_string($data_value);
            $this-〉db-〉query(“update `sessions` set “
                                    . “`user_id` = '{$data['user_id']}', “
                                    . “`data_value` = '$data_value', “
                                    . “`last_visit` = null “
                                    . “where `session_id` = '$session_id'“);
            return true;
        }
        function destroy($session_id) {
            $session_id = $this-〉db-〉escape_string($session_id);
            $this-〉db-〉query(“delete from `sessions` where `session_id` = '$session_id'“);
            return true;
        }
        function gc($lifetime) {
            $this-〉db-〉query(“delete from `sessions` where unix_timestamp(now()) - unix_timestamp(`last_visit`) 〉 $lifetime“);
            return true;
        }
        // get sessions by user_id
        function get($user_id) {
            $user_id = $this-〉db-〉escape_string($user_id);
            return $this-〉db-〉query(“select * from `sessions` where `user_id` = '$user_id'“);
        }
        // get sessions list
        function lists($page, $rows) {
            if ($page == 0) {
                return $this-〉db-〉query(“select * from `sessions` order by `user_id`“);
            }
            else {
                $start = ($page - 1) * $rows;
                return $this-〉db-〉query(“select * from `sessions` order by `user_id` limit $start, $rows“);
            }
        }
    }
    ?〉

    这个类的使用很简单,在原来使用 session_start 的地方,替换成 $session = new session($db) 就可以了。$db 表示 sessions 表所在的数据库。

    另外可以用 get 方法来获取某个用户的所有会话信息,通过 lists 方法来得到所有用户会话列表。这样就可以方便的管理用户会话了。 

PHP 相关文章推荐
十天学会php(3)
Oct 09 PHP
php设计模式 Chain Of Responsibility (职责链模式)
Jun 26 PHP
PHP新手用的Insert和Update语句构造类
Mar 31 PHP
php实现的一个很好用HTML解析器类可用于采集数据
Sep 23 PHP
CodeIgniter框架提示Disallowed Key Characters的解决办法
Apr 21 PHP
php+highchats生成动态统计图
May 21 PHP
ThinkPHP应用模式扩展详解
Jul 16 PHP
Laravel中使用自己编写类库的3种方法
Feb 10 PHP
PHP如何将XML转成数组
Apr 04 PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
Nov 17 PHP
laravel框架中间件 except 和 only 的用法示例
Jul 12 PHP
解决Laravel5.x的php artisan migrate数据库迁移创建操作报错SQLSTATE[42000]
Apr 06 PHP
PHP 编程请选择正确的文本编辑软件
Dec 21 #PHP
PHP 模板高级篇总结
Dec 21 #PHP
PHP函数utf8转gb2312编码
Dec 21 #PHP
小偷PHP+Html+缓存
Dec 20 #PHP
PR值查询 | PageRank 查询
Dec 20 #PHP
转PHP手册及PHP编程标准
Dec 17 #PHP
IIS环境下快速安装、配置和调试PHP5.2.0
Dec 17 #PHP
You might like
PHP实现MySQL更新记录的代码
2008/06/07 PHP
php 删除一个数组中的某个值.兼容多维数组!
2012/02/18 PHP
php可应用于面包屑导航的迭代寻找家谱树实现方法
2015/02/02 PHP
简单解决新浪SAE无法上传文件的问题
2015/05/13 PHP
WordPress中自定义后台管理界面配色方案的小技巧
2015/12/29 PHP
PHP命名空间namespace的定义方法详解
2017/03/29 PHP
php实现微信公众号企业转账功能
2018/10/01 PHP
JS对HTML标签select的获取、添加、删除操作
2013/10/17 Javascript
关于JavaScript作用域你想知道的一切
2016/02/04 Javascript
jQuery事件绑定on()与弹窗实现代码
2016/04/28 Javascript
第二篇Bootstrap起步
2016/06/21 Javascript
jQuery EasyUI Tab 选项卡问题小结
2016/08/16 Javascript
详解Vue.js——60分钟组件快速入门(上篇)
2016/12/05 Javascript
jQuery树控件zTree使用方法详解(一)
2017/02/28 Javascript
详解微信小程序胶囊按钮返回|首页自定义导航栏功能
2019/06/14 Javascript
详解微信小程序支付流程与梳理
2019/07/16 Javascript
在vue中实现禁止屏幕滚动,禁止屏幕滑动
2020/07/22 Javascript
用JavaScript实现贪吃蛇游戏
2020/10/23 Javascript
[00:35]DOTA2上海特级锦标赛 MVP.Phx战队宣传片
2016/03/04 DOTA
python实现批量获取指定文件夹下的所有文件的厂商信息
2014/09/28 Python
详解python如何调用C/C++底层库与互相传值
2016/08/10 Python
使用pandas对两个dataframe进行join的实例
2018/06/08 Python
Python ORM编程基础示例
2020/02/02 Python
在Python中用GDAL实现矢量对栅格的切割实例
2020/03/11 Python
python爬虫泛滥的解决方法详解
2020/11/25 Python
几个解决兼容IE6\7\8不支持html5标签的几个方法
2013/01/07 HTML / CSS
关于递归的一道.NET面试题
2013/05/12 面试题
物流经理自我评价
2013/09/23 职场文书
办公室内勤工作职责
2013/12/11 职场文书
甘南现象心得体会
2014/09/11 职场文书
2014广电局实施党的群众路线教育实践活动方案思想汇报
2014/09/22 职场文书
文明班级申报材料
2014/12/24 职场文书
《用字母表示数》教学反思
2016/02/17 职场文书
2016年感恩母亲节活动总结
2016/04/01 职场文书
七年级作文之我的梦想
2019/10/16 职场文书
python设置 matplotlib 正确显示中文的四种方式
2021/05/10 Python