首页 > 编程笔记 > PHP笔记

PHP session_set_save_handler():将Session存储到数据库

通过前面的学习我们知道,Session 是存储在服务器的临时目录中的,当站点的登陆人数较多时,也就意味着服务器中会存储大量的 Session 文件,很占服务器资源。而服务器想要在这众多的 Session 中查找指定的 Session_id 也并不是什么轻松的事情。出现这种情况时该怎么办呢?这时我们可以选择将 Session 存储到数据库中,以减轻服务器的压力。

PHP 中的 session_set_save_handler() 函数可以设置自定义的会话存储函数,通过这些自定义函数来操作 Session,从而将 Session 信息存储到数据库中。session_set_save_handler() 函数有两种形式,其语法格式如下:

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

参数说明如下:

除了上面这种形式,session_set_save_handler() 函数还有另外一种形式(自 PHP5.4 及以上版本可用),如下所示:

session_set_save_handler(object $sessionhandler [, bool $register_shutdown = TRUE])

参数说明如下:

一般函数的参数都是直接使用变量,但是 session_set_save_handler() 函数中却是以多个函数的名称作为参数。下面将通过示例的形式对这几个参数(函数)分别进行讲解。

1) 封装 sess_open() 函数,用来连接数据库,示例代码如下:
<?php
    // 连接数据库
    function sess_open($savePath, $sessionName){
        global $link;
        $link = mysqli_connect('localhost', 'root', 'root') or die('数据库连接失败!');
        mysqli_select_db($link, 'testdb') or die('未找到该数据库!');
        return true;
    }
?>
函数中并没有用到 $save_path 和 $session_name 这两个参数,可以将它们去掉,但是建议读者保留这两个参数,因为一般使用时都是存在这两个变量的,应该养成一个好的习惯。

2) 封装 sess_close() 函数,用来关闭数据库连接,示例代码如下:
<?php
    // 关闭数据库连接
    function sess_close(){
        global $link;
        mysqli_close($link);
        return true;
    }
?>
在这个函数中不需要任何参数,所以不论是将 Session 存储到数据库还是文件中,都只需返回 true 即可。但是这里是将 Session 存储到数据库中,所以最好还是在这里将数据库关闭,以避免出现其它问题。

3) 封装 sess_read() 函数,根据参数 $sessionId 来获取 Session 的信息,示例代码如下:
<?php
    // 读取 Session 内容
    function sess_read($sessionId){
        global $link;
        $time = time();
        $sql = "SELECT data FROM session WHERE id = '$sessionId' AND lapse_time > '$time'";
        $result = mysqli_query($link, $sql);
        $row = mysqli_fetch_array($result, MYSQLI_ASSOC);
        if($row){
            return $row['data'];
        }else{
            return false;
        }
    }
?>
4) 封装 sess_write() 函数,用来将 Session 内容写入数据库,示例代码如下:
<?php
    // 写入 Session
    function sess_write($sessionId, $data){
        global $link;
        $lapse_time = time()+(60*60);
        $sql = "SELECT data FROM session WHERE id = '$sessionId'";
        $result = mysqli_query($link, $sql);
        if(mysqli_num_rows($result) == 0){
            $ins_sql = "INSERT INTO session VALUES('$sessionId', '$data', '$lapse_time')";
            $res = mysqli_query($link, $ins_sql);
        }else{
            $up_sql = "UPDATE session SET data = '$data', lapse_time = '$lapse_time' WHERE id = '$sessionId'";
            $res = mysqli_query($link, $up_sql);
        }
        return $res;
    }
?>
5) 封装 sess_destroy() 函数,用来删除指定的 Session 数据,示例代码如下:
<?php
    // 删除 Session
    function sess_destroy($sessionId){
        global $link;
        $sql = "DELETE FROM session WHERE id = '$sessionId'";
        return mysqli_query($link, $sql);
    }
?>
6) 封装 sess_gc() 函数,用来清理失效的 Session,示例代码如下:
<?php
    // 清理失效的 Session
    function sess_gc(){
        global $link;
        $time = time();
        $sql = "DELETE FROM session WHERE lapse_time < '$time'";
        $res = mysqli_query($link, $sql);
        return $res;
    }
?>
以上定义的 6 个函数便是 session_set_save_handler() 函数 6 个必选参数,调用 session_set_save_handler() 函数即可实现将 Session 存储到数据库中,示例代码如下:
<?php
    ini_set("session.save_handler", "user");
    session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy', 'sess_gc');
    session_start();
    $_SESSION['user'] = 'admin';
?>
运行上面的代码即可将 user = 'admin' 的 Session 信息写入到数据库,如下所示:

mysql> SELECT * FROM session;
+--------------------------------+-------------------+--------------+
| id                                             | data                     | lapse_time    |
+--------------------------------+-------------------+--------------+
| c91mct86sfs3gs9lpke225b8ir | user|s:5:"admin";  | 1595587392 |
+--------------------------------+-------------------+--------------+
1 row in set (0.00 sec)

上面代码中 ini_set("session.save_handler", "user"); 用来临时修改 PHP 的配置信息,与直接将 php.ini 配置文件中 session.save_handler 的值改为 user 效果相同。另外需要注意的是,以上代码仅在 PHP7.0 版本中成功运行,其它版本暂未测试通过。

所有教程

优秀文章