欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

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

程序员文章站 2022-04-23 16:40:06
...
直接上代码:
复制代码 代码如下:

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 {
$sql = ‘DELETE FROM ‘ . $this->_config[‘tablename'] . ‘
WHERE heartbeat _config[‘cookie_timeout']) . ‘'‘;

$this->_mysqli->query($sql);
}
}

public function __destruct()
{
$this->_save();
$this->_gc();
$this->_mysqli->close();
}

}