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独立Session数据库存储操作类分享
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@