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

直接上代码

代码如下:
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'],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),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,$secure);
}
}
else
{
setcookie($name,$this->_config[‘cookiepath'],$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();
}

}

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...