PHP独立Session数据库存储操作类分享


Posted in PHP onJune 11, 2014

直接上代码:

class DbSession
{
    const TYPE_INT = 1;
    const TYPE_STR = 2;
    /**
     * Database configration
     *
     * @var array
     */
    private $_config = array(
            ‘host' => '127.0.0.1′,
            ‘port' => 3306,
            ‘username' => ‘root',
            ‘password' => ‘root',
            ‘dbname' => ‘db_mylab',
        ‘tablename' => ‘t_sessions',
        ‘cookie_prefix' => ‘mylab_',
        ‘cookiepath' => ‘/',
        ‘cookiedomain' => ”,
        ‘cookie_timeout' => 900
    );
    /**
     * Table fields type array
     *
     * @var array
     */
    private  $_db_fields = array(
        ‘crc32sid'      => self::TYPE_INT,
                ‘sessionhash'   => self::TYPE_STR,
                ‘idhash'        => self::TYPE_STR,
                ‘userid'        => self::TYPE_INT,
                ‘ipaddress'     => self::TYPE_STR,
                ‘lastactivity'  => self::TYPE_STR,
                ‘location'      => self::TYPE_STR,
        ‘loggedin'      => self::TYPE_INT,
        ‘heartbeat'     => self::TYPE_STR
        );
        /**
         * db obj
         *
         * @var mysqli object
         */
    private $_mysqli = null;
    /**
     * Weather the session was created or existed previously
     *
     * @var bool
     */
    private $_created = false;
    /**
     * Array of changes.
     *
     * @var array
     */
    private $_changes = array();
    /**
     * @var bool
     */
    private $_db_inited = false;
    /**
     * session host
     *
     * @var string
     */
    private $_session_host = ”;
    /**
     * session idhash
     *
     * @var string
     */
    private $_session_idhash = ”;
    private $_dbsessionhash = ”;
    private $_vars = array();
        public function __construct()
        {
                $this->_dbsessionhash = addslashes($this->get_cookie(‘sessionhash'));
            $this->_session_host = substr($_SERVER[‘REMOTE_ADDR'], 0, 15);
            #This should *never* change during a session
            $this->_session_idhash = md5($_SERVER[‘HTTP_USER_AGENT'] . self::fetch_substr_ip(self::fetch_alt_ip()) );
            $this->_init_config();
            $this->init_db();
            $gotsession = false;
            if ($this->_dbsessionhash)
            {
                $sql = ‘
                        SELECT *
                        FROM ‘ . $this->_config[‘tablename'] . ‘
                        WHERE   crc32sid = ‘ . sprintf(‘%u', crc32($this->_dbsessionhash)) . ‘
                            AND sessionhash = '‘ . $this->_dbsessionhash . ‘'
                                AND idhash = '‘ . $this->_session_idhash . ‘'
                        AND heartbeat > '‘ . date(‘Y-m-d H:i:s' ,TIMENOW ? $this->_config[‘cookie_timeout']) . ‘'‘;
                    //echo $sql;exit;
                $result = $this->_mysqli->query($sql);
                $session = $result->fetch_array(MYSQLI_ASSOC);
                if ($session AND ($this->fetch_substr_ip($session[‘ipaddress']) == $this->fetch_substr_ip($this->_session_host)))
                {
                        $gotsession = true;
                        $this->_vars = $session;
                        $this->_created = false;
                }
            }
            if ($gotsession == false)
            {
                $this->_vars = $this->fetch_session();
                $this->_created = true;
                $gotsession = true;
            }
            if ($this->_created == false)
            {
            $this->set(‘lastactivity', date(‘Y-m-d H:i:s', TIMENOW));
            $this->set(‘location', $_SERVER[‘REQUEST_URI']);
            }
        }
    /**
     * Builds an array that can be used to build a query to insert/update the session
     *
     * @return    array    Array of column name => prepared value
     */
    private function _build_query_array()
    {
        $return = array();
        foreach ($this->_db_fields AS $fieldname => $cleantype)
        {
            switch ($cleantype)
            {
                case self::TYPE_INT:
                    $cleaned = is_numeric($this->_vars["$fieldname"]) ? $this->_vars["$fieldname"] : intval($this->_vars["$fieldname"]);
                    break;
                case self::TYPE_STR:
                default:
                    $cleaned = "'" . addslashes($this->_vars["$fieldname"]) . "'";
            }
            $return["$fieldname"] = $cleaned;
        }
        return $return;
    }
    /**
     * Sets a session variable and updates the change list.
     *
     * @param    string    Name of session variable to update
     * @param    string    Value to update it with
     */
    public function set($key, $value)
    {
        if ($this->_vars["$key"] != $value)
        {
            $this->_vars["$key"] = $value;
            $this->_changes["$key"] = true;
        }
    }
    public function get($key)
    {
        return $this->_vars["$key"];
    }
        public function unsetchangedvar($var)
    {
        if (isset($this->_changes["$var"]))
        {
                unset($this->_changes["$var"]);
        }
    }
    /**
     * Fetches a valid sessionhash value, not necessarily the one tied to this session.
     *
     * @return    string    32-character sessionhash
     */
    static function fetch_sessionhash()
    {
        return hash(‘md5′ , TIMENOW . rand(1, 100000) . uniqid() );
    }
        private function _init_config()
        {
                $registry = Zend_Registry::getInstance();
                $config = $registry->get(‘config');
                $this->_config[‘host'] = $config->database->params->host;
        $this->_config[‘port'] = $config->database->params->port;
        $this->_config[‘username'] = $config->database->params->username;
        $this->_config[‘password'] = $config->database->params->password;
        $this->_config[‘dbname'] = $config->database->params->dbname;
        $this->_config[‘tablename'] = $config->database->session->tablename;
        }
        /**
         * initialize database connection
         */
        public function init_db()
        {
            if ($this->_db_inited)
            {
                return true;
            }
            //mysqli_report(MYSQLI_REPORT_OFF);
            $this->_mysqli = new mysqli(
                $this->_config[‘host'],
                $this->_config[‘username'],
                $this->_config[‘password'],
                $this->_config[‘dbname'],
                $this->_config[‘port']
            );
            /* check connection */
                if (mysqli_connect_errno())
                {
                    // printf("Connect failed: %sn", mysqli_connect_error());
                    // echo ‘in ‘, __FILE__, ‘ on line ‘, __LINE__;
                    echo "{ success: false, errors: { reason: ‘ Connect failed: " . addslashes( mysqli_connect_error() ) . "' }}";
                    exit();
                }
            $this->_mysqli->query(‘set names latin1′);
            $this->_db_inited = true;
            return true;
        }
    /**
         * Fetches an alternate IP address of the current visitor, attempting to detect proxies etc.
         *
         * @return      string
         */
        static function fetch_alt_ip()
        {
                $alt_ip = $_SERVER[‘REMOTE_ADDR'];
                if (isset($_SERVER[‘HTTP_CLIENT_IP']))
                {
                        $alt_ip = $_SERVER[‘HTTP_CLIENT_IP'];
                }
                else if (isset($_SERVER[‘HTTP_FROM']))
                {
                        $alt_ip = $_SERVER[‘HTTP_FROM'];
                }
                return $alt_ip;
        }
    /**
     * Returns the IP address with the specified number of octets removed
     *
     * @param    string    IP address
     *
     * @return    string    truncated IP address
     */
    static function fetch_substr_ip($ip, $length = null)
    {
        return implode(‘.', array_slice(explode(‘.', $ip), 0, 4 ? $length));
    }
    /**
     * Fetches a default session. Used when creating a new session.
     *
     * @param    integer    User ID the session should be for
     *
     * @return    array    Array of session variables
     */
    public function fetch_session($userid = 0)
    {
        $sessionhash = self::fetch_sessionhash();
        $this->set_cookie(‘sessionhash', $sessionhash);
        return array(
            ‘crc32sid'      => sprintf(‘%u', crc32($sessionhash)),
            ‘sessionhash'   => $sessionhash,
            ‘idhash'        => $this->_session_idhash,
            ‘userid'        => $userid,
            ‘ipaddress'     => $this->_session_host,
            ‘lastactivity'  => date(‘Y-m-d H:i:s', TIMENOW),
            ‘location'      => $_SERVER[‘REQUEST_URI'],
            ‘loggedin'      => $userid ? 1 : 0,
            ‘heartbeat'     => date(‘Y-m-d H:i:s', TIMENOW)
        );
    }
    public function get_cookie($cookiename)
    {
        $full_cookiename = $this->_config[‘cookie_prefix'] . $cookiename;
        if (isset($_COOKIE[$full_cookiename]))
        {
            return $_COOKIE[$full_cookiename];
        }
        else
        {
            return  false;
        }
    }
    public function set_cookie($name, $value = ”, $permanent = 1, $allowsecure = true)
    {
        if ($permanent)
        {
            $expire = TIMENOW + 60 * 60 * 24 * 365;
        }
        else
        {
            $expire = 0;
        }
        if ($_SERVER[‘SERVER_PORT'] == '443′)
        {
            // we're using SSL
            $secure = 1;
        }
        else
        {
            $secure = 0;
        }
        // check for SSL
        $secure = ((REQ_PROTOCOL === ‘https' AND $allowsecure) ? true : false);
        $name = $this->_config[‘cookie_prefix'] . $name;
        $filename = ‘N/A';
        $linenum = 0;
        if (!headers_sent($filename, $linenum))
        { // consider showing an error message if there not sent using above variables?
            if ($value == ” AND strlen($this->_config[‘cookiepath']) > 1 AND strpos($this->_config[‘cookiepath'], ‘/') !== false)
            {
                // this will attempt to unset the cookie at each directory up the path.
                // ie, cookiepath = /test/abc/. These will be unset: /, /test, /test/, /test/abc, /test/abc/
                // This should hopefully prevent cookie conflicts when the cookie path is changed.
                $dirarray = explode(‘/', preg_replace(‘#/+$#', ”, $this->_config[‘cookiepath']));
                $alldirs = ”;
                foreach ($dirarray AS $thisdir)
                {
                    $alldirs .= "$thisdir";
                    if (!empty($thisdir))
                    { // try unsetting without the / at the end
                        setcookie($name, $value, $expire, $alldirs, $this->_config[‘cookiedomain'], $secure);
                    }
                    $alldirs .= "/";
                    setcookie($name, $value, $expire, $alldirs, $this->_config[‘cookiedomain'], $secure);
                }
            }
            else
            {
                setcookie($name, $value, $expire, $this->_config[‘cookiepath'], $this->_config[‘cookiedomain'], $secure);
            }
        }
        else if (!DEBUG)
        {
            echo "can't set cookies";
        }
    }
        private function _save()
        {
            $cleaned = $this->_build_query_array();
            if ($this->_created)
            {
                //var_dump($cleaned);
                # insert query
                $this->_mysqli->query(‘
                        INSERT IGNORE INTO ‘ . $this->_config[‘tablename'] . ‘
                        (‘ . implode(‘,', array_keys($cleaned)) . ‘)
                    VALUES
                        (‘ . implode(‘,', $cleaned). ‘)
                ‘);
            }
            else
            {
                # update query
                $update = array();
            foreach ($cleaned AS $key => $value)
            {
                if (!empty($this->_changes["$key"]))
                {
                    $update[] = "$key = $value";
                }
            }
            if (sizeof($update) > 0)
            {
                $sql = ‘UPDATE ‘ . $this->_config[‘tablename'] . ‘
                        SET ‘ . implode(‘, ‘, $update) . ‘
                        WHERE crc32sid = ‘ . sprintf(‘%u', crc32($this->_dbsessionhash)) . ‘
                            AND sessionhash = '‘ . $this->_dbsessionhash . ‘'‘;
                //echo $sql;
                $this->_mysqli->query($sql);
            }
            }
        }
        public function getOnlineUserNum()
        {
                $sql = ‘
                        SELECT count(*) as cnt
                        FROM ‘ . $this->_config[‘tablename'] . ‘
                        WHERE loggedin = 1
                          AND heartbeat > '‘ . date(‘Y-m-d H:i:s' ,TIMENOW ? $this->_config[‘cookie_timeout']) . ‘'‘;
            $result = $this->_mysqli->query($sql);
            $row = $result->fetch_array(MYSQLI_ASSOC);
                return $row[‘cnt'];
        }
        private function _gc()
        {
                $rand_num = rand(); # randow integer between 0 and getrandmax()
                if ($rand_num < 100)
                {
                        $sql = ‘DELETE FROM ‘ . $this->_config[‘tablename'] . ‘
                                WHERE heartbeat < '‘ . date(‘Y-m-d H:i:s' ,TIMENOW ? $this->_config[‘cookie_timeout']) . ‘'‘;
                        $this->_mysqli->query($sql);
                }
        }
        public function __destruct()
        {
            $this->_save();
            $this->_gc();
            $this->_mysqli->close();
        }
}

 

PHP 相关文章推荐
第1次亲密接触PHP5(2)
Oct 09 PHP
在PHP中养成7个面向对象的好习惯
Jan 28 PHP
PHP系列学习之日期函数使用介绍
Aug 18 PHP
php验证手机号码(支持归属地查询及编码为UTF8)
Feb 01 PHP
解析php如何将日志写进syslog
Jun 28 PHP
用PHP来计算某个目录大小的方法
Apr 01 PHP
微信公众号点击菜单即可打开并登录微站的实现方法
Nov 14 PHP
PHP实现通用alert函数的方法
Mar 11 PHP
php实现图片缩略图的方法
Mar 29 PHP
Yii2框架实现数据库常用操作总结
Feb 08 PHP
php反射学习之依赖注入示例
Jun 14 PHP
详解使用php-cs-fixer格式化代码
Sep 16 PHP
php调用nginx的mod_zip模块打包ZIP文件
Jun 11 #PHP
php+ajax导入大数据时产生的问题处理
Jun 11 #PHP
CI框架中libraries,helpers,hooks文件夹详细说明
Jun 10 #PHP
PHP图片等比例缩放生成缩略图函数分享
Jun 10 #PHP
CI(CodeIgniter)框架中的增删改查操作
Jun 10 #PHP
PHP定时更新程序设计思路分享
Jun 10 #PHP
CI(CodeIgniter)框架配置
Jun 10 #PHP
You might like
PHP学习笔记 (1) 环境配置与代码调试
2011/06/19 PHP
php后台如何避免用户直接进入方法实例
2013/10/15 PHP
php cookie名使用点号(句号)会被转换
2014/10/23 PHP
PHP自定义图片缩放函数实现等比例不失真缩放的方法
2016/08/19 PHP
thinkphp5+layui实现的分页样式示例
2019/10/08 PHP
Extjs TimeField 显示正常时间格式的代码
2011/06/28 Javascript
jquery 操作日期、星期、元素的追加的实现代码
2012/02/07 Javascript
ScrollDown的基本操作示例
2013/06/09 Javascript
JS判断对象是否存在的10种方法总结
2013/12/23 Javascript
Jquery遍历checkbox获取选中项value值的方法
2014/02/13 Javascript
jQuery mobile类库使用时加载导航历史的方法简介
2015/12/04 Javascript
详解JavaScript中localStorage使用要点
2016/01/13 Javascript
图文详解JavaScript的原型对象及原型链
2016/08/02 Javascript
JS在Chrome浏览器中showModalDialog函数返回值为undefined的解决方法
2016/08/03 Javascript
JS中微信小程序自定义底部弹出框
2016/12/22 Javascript
JavaScript实现的浏览器下载文件的方法
2017/08/09 Javascript
Vux+Axios拦截器增加loading的问题及实现方法
2018/11/08 Javascript
基于vue写一个全局Message组件的实现
2019/08/15 Javascript
vue实现广告栏上下滚动效果
2020/11/26 Vue.js
Python列表append和+的区别浅析
2015/02/02 Python
Pycharm设置界面全黑的方法
2018/05/23 Python
Python中的random.uniform()函数教程与实例解析
2019/03/02 Python
Python用类实现扑克牌发牌的示例代码
2020/06/01 Python
PyTorch预训练Bert模型的示例
2020/11/17 Python
Timberland德国官网:靴子、鞋子、衣服、夹克及配件
2019/12/10 全球购物
期末总结的个人自我评价
2013/11/02 职场文书
小型女装店的创业计划书
2014/01/09 职场文书
四风存在的原因分析
2014/02/11 职场文书
酒店员工检讨书
2014/02/18 职场文书
环境保护标语
2014/06/20 职场文书
企业百日安全活动总结
2015/05/07 职场文书
关于法制教育的宣传语
2015/07/13 职场文书
2015初中团支部工作总结
2015/07/21 职场文书
2016年教师节贺卡寄语
2015/12/04 职场文书
导游词之新疆-喀纳斯
2019/10/10 职场文书
HTTP中的Content-type详解
2022/01/18 HTML / CSS