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 相关文章推荐
用PHP读取flv文件的播放时间长度
Sep 03 PHP
一个简单php扩展介绍与开发教程
Aug 19 PHP
Drupal 添加模块出现莫名其妙的错误的解决方法(往往出现在模块较多时)
Apr 18 PHP
php从数组中随机抽取一些元素的代码
Nov 05 PHP
深入理解:单一入口、MVC、ORM、CURD、ActiveRecord概念
Jun 06 PHP
探讨捕获php错误信息方法的详解
Jun 09 PHP
php实现aes加密类分享
Feb 16 PHP
php实现从上传文件创建缩略图的方法
Apr 02 PHP
浅谈PHP的反射机制
Dec 15 PHP
PHP实现移除数组中为空或为某值元素的方法
Jan 07 PHP
laravel实现分页样式替换示例代码(增加首、尾页)
Sep 22 PHP
swoole锁的机制代码实例讲解
Mar 04 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
Zend Framework教程之Application和Bootstrap用法详解
2016/03/10 PHP
PHP+Mysql+Ajax实现淘宝客服或阿里旺旺聊天功能(前台页面)
2017/06/16 PHP
通用于ie和firefox的函数 GetCurrentStyle (obj, prop)
2006/12/27 Javascript
Web层改进II-用xmlhttp 无声息提交复杂表单
2007/01/22 Javascript
select组合框option的捕捉实例代码
2008/09/30 Javascript
javascript学习笔记(七)利用javascript来创建和存储cookie
2011/04/08 Javascript
js加强的经典分页实例
2013/03/15 Javascript
nodejs开发微博实例
2015/03/25 NodeJs
JavaScript动态修改背景颜色的方法
2015/04/16 Javascript
JS调用打印机功能简单示例
2016/11/28 Javascript
jQuery UI制作选项卡(tabs)
2016/12/13 Javascript
详解Angular.js指令中scope类型的几种特殊情况
2017/02/21 Javascript
Vue组件通信实践记录(推荐)
2017/08/15 Javascript
详解从买域名到使用pm2部署node.js项目全过程
2018/03/07 Javascript
Vue组件中的data必须是一个function的原因浅析
2018/09/03 Javascript
6行代码实现微信小程序页面返回顶部效果
2018/12/28 Javascript
多个vue子路由文件自动化合并的方法
2019/09/03 Javascript
WEEX环境搭建与入门详解
2019/10/16 Javascript
Vue-router中hash模式与history模式的区别详解
2020/12/15 Vue.js
python Django模板的使用方法(图文)
2013/11/04 Python
读写json中文ASCII乱码问题的解决方法
2016/11/05 Python
Python3.5局部变量与全局变量作用域实例分析
2019/04/30 Python
浅谈pyqt5在QMainWindow中布局的问题
2019/06/21 Python
Keras模型转成tensorflow的.pb操作
2020/07/06 Python
Desigual德国官网:在线购买原创服装
2018/03/27 全球购物
三维科技面试题
2013/07/27 面试题
如何利用find命令查找文件
2016/11/18 面试题
英语简历自我评价
2014/01/26 职场文书
最新结婚典礼主持词
2014/03/14 职场文书
节约用水倡议书
2014/04/16 职场文书
英语课外活动总结
2014/08/27 职场文书
乡镇遵守党的政治纪律情况对照检查材料
2014/09/26 职场文书
电子银行业务授权委托书
2014/10/10 职场文书
党内外群众意见范文
2015/06/02 职场文书
小学生暑假安全保证书
2015/07/13 职场文书
教你用Python爬取英雄联盟皮肤原画
2021/06/13 Python