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

前端技术 2023/09/01 PHP

直接上代码:

复制代码 代码如下:

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();
        }

}

本文地址:https://www.stayed.cn/item/2090

转载请注明出处。

本站部分内容来源于网络,如侵犯到您的权益,请 联系我

我的博客

人生若只如初见,何事秋风悲画扇。