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初学者头疼十四条问题大总结
Nov 12 PHP
PHP下一个非常全面获取图象信息的函数
Nov 20 PHP
PHP 加密与解密的斗争
Apr 17 PHP
php侧拉菜单 漂亮,可以向右或者向左展开,支持FF,IE
Oct 15 PHP
用 Composer构建自己的 PHP 框架之使用 ORM
Oct 30 PHP
php实现encode64编码类实例
Mar 24 PHP
Symfony2 session用法实例分析
Feb 04 PHP
PHP 二维数组和三维数组的过滤
Mar 16 PHP
php 时间time与日期date之间的使用详解及区别
Nov 07 PHP
PHP中时间加减函数strtotime用法分析
Apr 26 PHP
PHP删除二维数组中相同元素及数组重复值的方法示例
May 05 PHP
TP5框架实现自定义分页样式的方法示例
Apr 05 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 empty() 检查一个变量是否为空
2011/11/10 PHP
PDO::beginTransaction讲解
2019/01/27 PHP
Laravel访问出错提示:`Warning: require(/vendor/autoload.php): failed to open stream: No such file or di解决方法
2019/04/02 PHP
javascript 动态添加表格行
2006/06/22 Javascript
背景图跟随鼠标移动的Mootools插件实现代码
2011/12/12 Javascript
js简易namespace管理器 实例代码
2013/06/21 Javascript
jQuery表单获取和失去焦点输入框提示效果的实例代码
2013/08/01 Javascript
网页中可关闭的漂浮窗口实现可自行调节
2013/08/20 Javascript
document.addEventListener使用介绍
2014/03/07 Javascript
jquery插件unobtrusive实现片段式加载
2015/06/15 Javascript
jQuery插件开发精品教程(让你的jQuery更上一个台阶)
2015/11/07 Javascript
JS组件Bootstrap实现弹出框效果代码
2016/04/26 Javascript
一个字符串中出现次数最多的字符 统计这个次数【实现代码】
2016/04/29 Javascript
JavaScript中获取时间的函数集
2016/08/16 Javascript
Node.js读写文件之批量替换图片的实现方法
2016/09/07 Javascript
基于JavaScript实现拖动滑块效果
2017/02/16 Javascript
vue使用watch 观察路由变化,重新获取内容
2017/03/08 Javascript
PWA介绍及快速上手搭建一个PWA应用的方法
2019/01/27 Javascript
PHP魔术方法__ISSET、__UNSET使用实例
2014/11/25 Python
Python中模块与包有相同名字的处理方法
2017/05/05 Python
python生成tensorflow输入输出的图像格式的方法
2018/02/12 Python
python flask实现分页的示例代码
2018/08/02 Python
Python做智能家居温湿度报警系统
2018/09/25 Python
CentOS 7 安装python3.7.1的方法及注意事项
2018/11/01 Python
python Popen 获取输出,等待运行完成示例
2019/12/30 Python
浅谈pytorch 模型 .pt, .pth, .pkl的区别及模型保存方式
2020/05/25 Python
高中数学教师求职信
2013/10/30 职场文书
大学生应聘推荐信范文
2013/11/19 职场文书
大学生村官工作感言
2014/01/10 职场文书
小学生演讲稿
2014/01/12 职场文书
安全承诺书格式
2014/05/21 职场文书
大学四年个人总结
2015/03/03 职场文书
无保留意见审计报告
2015/06/05 职场文书
2016形势与政策学习心得体会
2016/01/12 职场文书
Python趣味挑战之给幼儿园弟弟生成1000道算术题
2021/05/28 Python
python之np.argmax()及对axis=0或者1的理解
2021/06/02 Python