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 curl 登录163邮箱并抓取邮箱好友列表的代码(经测试)
Apr 07 PHP
PHP实现邮件群发的源码
Jun 18 PHP
关于PHP内存溢出问题的解决方法
Jun 25 PHP
PHP 过滤页面中的BOM(实现代码)
Jun 29 PHP
php数组索引的Key加引号和不加引号的区别
Aug 19 PHP
PHP字符串比较函数strcmp()和strcasecmp()使用总结
Nov 19 PHP
PHP中创建图像并绘制文字的例子
Nov 19 PHP
PHP附件下载中文名称乱码的解决方法
Dec 17 PHP
分析PHP中单双引号的误区和双引号小隐患
Jul 19 PHP
PHP实现的简单适配器模式示例
Jun 22 PHP
php获取ajax的headers方法与内容实例
Dec 27 PHP
PhpStorm本地断点调试的方法步骤
May 21 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获取是星期几的的一些常用姿势
2019/12/15 PHP
PHP7新特性
2021/03/09 PHP
如何用javascript控制上传文件的大小
2006/10/26 Javascript
js判断IE浏览器版本过低示例代码
2013/11/22 Javascript
JS 获取浏览器和屏幕宽高等信息代码
2014/03/31 Javascript
基于js与flash实现的网站flv视频播放插件代码
2014/10/14 Javascript
jQuery实现高亮显示的方法
2015/03/10 Javascript
JavaScript实现倒计时代码段Item1(非常实用)
2015/11/03 Javascript
适用于javascript开发者的Processing.js入门教程
2016/02/24 Javascript
判断iOS、Android以及PC端的示例代码
2018/11/15 Javascript
微信小程序template模板与component组件的区别和使用详解
2019/05/22 Javascript
JS实现简单随机3D骰子
2019/10/24 Javascript
JSONP 的原理、理解 与 实例分析
2020/05/16 Javascript
微信小程序手动添加收货地址省市区联动
2020/05/18 Javascript
OpenLayers3实现图层控件功能
2020/09/25 Javascript
Python中的pprint折腾记
2015/01/21 Python
python实现应用程序在右键菜单中添加打开方式功能
2017/01/09 Python
python爬取个性签名的方法
2018/06/17 Python
python三引号输出方法
2019/02/27 Python
了解不常见但是实用的Python技巧
2019/05/23 Python
python利用wx实现界面按钮和按钮监听和字体改变的方法
2019/07/17 Python
在python中实现同行输入/接收多个数据的示例
2019/07/20 Python
python实现指定ip端口扫描方式
2019/12/17 Python
Python 中Operator模块的使用
2021/01/30 Python
linux系统下pip升级报错的解决方法
2021/01/31 Python
AmazeUi Tree(树形结构) 应用小结
2020/08/17 HTML / CSS
Boden美国官网:英伦原创时装品牌
2017/07/03 全球购物
中国首家奢侈品O2O网购平台:第五大道奢侈品网
2017/12/14 全球购物
PHP如何对用户密码进行加密
2014/07/31 面试题
生物技术专业研究生自荐信
2013/09/22 职场文书
就业意向书范文
2014/04/01 职场文书
《青山处处埋忠骨》教学反思
2014/04/22 职场文书
运动会广播稿150字(9篇)
2014/09/20 职场文书
迟到检讨书
2015/01/26 职场文书
想要创业,那么你做好准备了吗?
2019/07/01 职场文书
送给自己的励志语句:要安静的优秀,悄无声息的坚强
2019/11/26 职场文书