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 相关文章推荐
程序员编程十条戒律
Jul 09 PHP
PHP之COOKIE支持详解
Sep 20 PHP
PHP无限分类(树形类)
Sep 28 PHP
php中try catch捕获异常实例详解
Nov 21 PHP
php通过array_merge()函数合并两个数组的方法
Mar 18 PHP
php超快高效率统计大文件行数
Jul 05 PHP
php微信浏览器分享设置以及回调详解
Aug 01 PHP
Symfony查询方法实例小结
Jun 28 PHP
Thinkphp5.0框架使用模型Model的获取器、修改器、软删除数据操作示例
Oct 11 PHP
浅谈Laravel POST,PUT,PATCH 路由的区别
Oct 15 PHP
Laravel 自定命令以及生成文件的例子
Oct 23 PHP
php适配器模式简单应用示例
Oct 23 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插入排序实现代码
2013/04/04 PHP
php数字运算验证码的实现代码
2015/07/30 PHP
php查看一个变量的占用内存的实例代码
2020/03/29 PHP
Laravel框架源码解析之模型Model原理与用法解析
2020/05/14 PHP
javascript中call和apply方法浅谈
2013/09/27 Javascript
Angular中的Promise对象($q介绍)
2015/03/03 Javascript
javascript实现table表格隔行变色的方法
2015/05/13 Javascript
javascript单例模式的简单实现方法
2015/07/25 Javascript
Javascript复制实例详解
2016/01/28 Javascript
jQuery插件AjaxFileUpload实现ajax文件上传
2016/05/05 Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
2016/10/11 Javascript
vuejs开发组件分享之H5图片上传、压缩及拍照旋转的问题处理
2017/03/06 Javascript
Mac下安装vue
2018/04/11 Javascript
js类的继承定义与用法分析
2019/06/21 Javascript
详解Vscode中使用Eslint终极配置大全
2019/11/08 Javascript
jquery实现直播视频弹幕效果
2020/02/25 jQuery
[01:27]2014DOTA2展望TI 剑指西雅图IG战队专访
2014/06/30 DOTA
Python版微信红包分配算法
2015/05/04 Python
Python随机生成手机号、数字的方法详解
2017/07/21 Python
Python单元测试unittest的具体使用示例
2018/12/17 Python
python使用pandas处理excel文件转为csv文件的方法示例
2019/07/18 Python
基于pytorch中的Sequential用法说明
2020/06/24 Python
CSS3 filter(滤镜)实现网页灰色或者黑色模式的代码
2020/11/30 HTML / CSS
HTML5中的Article和Section元素认识及使用
2013/03/22 HTML / CSS
购买大码女装:Lane Bryant
2016/09/07 全球购物
请介绍一下Ant
2016/07/22 面试题
abstract是什么意思
2012/02/12 面试题
物业经理求职自我评价
2013/09/22 职场文书
母亲80寿诞答谢词
2014/01/16 职场文书
《灯光》教学反思
2014/02/08 职场文书
企业精细化管理实施方案
2014/03/23 职场文书
2014年信访工作总结
2014/11/17 职场文书
2014年统战工作总结
2014/12/09 职场文书
家长对孩子的寒假评语
2015/10/09 职场文书
商业计划书范文
2019/04/24 职场文书
Redis+Lua脚本实现计数器接口防刷功能(升级版)
2022/02/12 Redis