• PHP session 写入数据库中的方法


        首先解释下为什么要把session 写到数据库中呢,session 一般默认是以文件的形式放在php.ini 配置的目录中的, 如果你的网站实现了多台服务器负载均衡,这样用户访问你的网站,可能进入的服务器就不同,如果没有实现吧session 文件在服务器上实现同步,那么就可能会出现session 丢失问题,最常见的例子就是,我登陆了后台,点着点着 就又让重新登录了,这是个典型的session 没有同步而引起的session 丢失的问题。

    解决方案当然有很多,现在介绍一个就是把用户的session 写入到数据库中去,这样session 都从数据库中读取,就不会有丢失的情况发生。

    首先要更改php.ini 里面
    session.save_handler = files
    为:
    session.save_handler = user

    PHP 有个session_set_save_handler() 函数 ,这个函数就是自定义处理session 的机制,一般 要定义 
    'open', 'close', 'read', 'write','destroy', 'gc'
    这几个函数 

    下面是个session 写入数据库的一个类

    <?php
    class SessionToDB
    {
        private $_path = null;
        private $_name = null;
        private $_pdo = null;
        private $_ip = null;
        private $_maxLifeTime = 0;
    
        public function __construct(PDO $pdo)
        {
            //注册处理session 的函数
            session_set_save_handler(
            array(&$this, 'open'),
            array(&$this, 'close'),
            array(&$this, 'read'),
            array(&$this, 'write'),
            array(&$this, 'destroy'),
            array(&$this, 'gc')
            );
    
            $this->_pdo = $pdo;
            $this->_ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
            $this->_maxLifeTime = ini_get('session.gc_maxlifetime');
        }
    
        public function open($path,$name)
        {
            return true;
        }
    
        public function close()
        {
            return true;
        }
        //读取函数
        public function read($id)
        {
            $sql = 'SELECT * FROM session where PHPSESSID = ?';
            $stmt = $this->_pdo->prepare($sql);
            $stmt->execute(array($id));
    
            if (!$result = $stmt->fetch(PDO::FETCH_ASSOC)) {
                return null;
            } elseif ($this->_ip != $result['client_ip']) {
                return null;
            } elseif ($result['update_time']+$this->_maxLifeTime < time()){
            $this->destroy($id);
                return null;
            } else {
                return $result['data'];
            }
        }
        //写入函数
        public function write($id,$data)
        {
            $sql = 'SELECT * FROM session where PHPSESSID = ?';
            $stmt = $this->_pdo->prepare($sql);
            $stmt->execute(array($id));
    
            if ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
                if ($result['data'] != $data) {
                    $sql = 'UPDATE session SET update_time =? , data = ? WHERE PHPSESSID = ?';
    
                    $stmt = $this->_pdo->prepare($sql);
                    $stmt->execute(array(time(), $data, $id));
                }
            } else {
                if (!empty($data)) {
                    $sql = 'INSERT INTO session (PHPSESSID, update_time, client_ip, data) VALUES (?,?,?,?)';
                    $stmt = $this->_pdo->prepare($sql);
                    $stmt->execute(array($id, time(), $this->_ip, $data));
                }
            }
            return true;
        }
        //销毁函数
        public function destroy($id)
        {
            $sql = 'DELETE FROM session WHERE PHPSESSID = ?';
            $stmt = $this->_pdo->prepare($sql);
            $stmt->execute(array($id));
            return true;
        }
        //这个函数执行的几率有php.ini 控制
        public function gc($maxLifeTime)
        {
            $sql = 'DELETE FROM session WHERE update_time < ?';
            $stmt = $this->_pdo->prepare($sql);
            $stmt->execute(array(time() - $maxLifeTime));
            return true;
        }
    }
    //调用方式
    ini_set('session.save_handler','user');//更改为user 方式
    ini_set('session.gc_maxlifetime', '86400');//session 最大有效期可以不设
    $dbname='数据库名称';
    $dbuser='用户名';
    $dbpwd=密码'';
    $dbhost='主机地址';
    try{
        $pdo = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser,$dbpwd);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
        new SessionToDB($pdo);
        session_start();
    } catch(PDOException $e) {
        echo 'Error: '.$e->getMessage();
    }
    ?>

    数据库结构:
    CREATE TABLE `session` (
    `PHPSESSID` varchar(50) NOT NULL,
    `update_time` int(10) NOT NULL,
    `client_ip` varchar(25) NOT NULL,
    `data` text NOT NULL,
    PRIMARY KEY (`PHPSESSID`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    当然解决这个问题的方法很多,思路就是把session 放到服务器 共用的地方.

  • 相关阅读:
    uniapp解决图形验证码问题及arraybuffer二进制转base64格式图片
    uni-app图片上传接口联调
    Redis与Mysql双写一致性方案解析(转载)
    python 3 for循环倒序、一组数据参数解包
    python使用for循环打印直角三角形、菱形、乘法口诀,1至100的和、奇数和、偶数和
    使用jmeter做接口测试,简单实例
    python发送无参数get请求
    python的第三方库unittestreport 详细功能使用文档(V1.1.1)-转载
    python 3 发送邮件(转载)
    python使用apscheduler执行定时任务时报错:Run time of job "pr (trigger: cron[minute='25'], next run at: 2021-05-05 22:25:00 CST)" was missed by 0:00:01.185258
  • 原文地址:https://www.cnblogs.com/guangxiaoluo/p/3337037.html
Copyright © 2020-2023  润新知