ecshop利用全局变量$_SESSION和register_shutdown_function自定义会话
2016-09-07 22:02 来源:www.chinab4c.com 作者:ecshop专家
在做ecshop的二次开发过程中,虽然代码 太老太乱太冗余,但ec的会话处理的设计感觉还是不错的,就使用了$_SESSION这个全局变量而已,这个设计是最好改善原来的会话处理方式的存数据库表的话,有2张表,sessions 表使用内存存储引擎,会话属于临时数据,这样存取速度很快,当然当临时数据很多时,会占用内存空间,对于较多的数据 还是需要存在磁盘上,这是就需要sessions_data 做一个sessions表的关联来存储较多的额外数据.register_shutdown_function 可以注册一个自定义的函数,在程序运行结束之前 执行。
表结构
CREATE TABLE `sessions` (
`sesskey` char(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`expiry` int(10) unsigned NOT NULL DEFAULT '0',
`userid` mediumint(8) unsigned NOT NULL DEFAULT '0',
`adminid` mediumint(8) unsigned NOT NULL DEFAULT '0',
`ip` char(15) NOT NULL DEFAULT '',
`user_name` varchar(60) NOT NULL,
`user_rank` tinyint(3) NOT NULL,
`discount` decimal(3,2) NOT NULL,
`email` varchar(60) NOT NULL,
`data` char(255) NOT NULL DEFAULT '',
PRIMARY KEY (`sesskey`),
KEY `expiry` (`expiry`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8;
CREATE TABLE `sessions_data` (
`sesskey` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`expiry` int(10) unsigned NOT NULL DEFAULT '0',
`data` longtext NOT NULL,
PRIMARY KEY (`sesskey`),
KEY `expiry` (`expiry`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
复制代码
程序文件根据ecshop的类有改动
cls_session.php
db.php 数据库处理
fun.php 用到的函数
init.php 初始化程序文件
--------------
两个demo程序
set.php
get.php
程序文件内容
cls_session.php
<?php
class cls_session
{
public $db = NULL;
public $session_table = '';
public $max_life_time = 1800;
public $session_name = '';
public $session_id = '';
public $session_expiry = '';
public $session_md5 = '';
public $session_cookie_path = '/';
public $session_cookie_domain = '';
public $session_cookie_secure = false;
public $_ip = '';
public $_time = 0;
public function __construct(&$db, $session_table, $session_data_table, $session_name = 'ECS_ID', $session_id = '')
{
$_SESSION = array();
$this->session_cookie_path = !empty($GLOBALS['cookie_path']) ? $GLOBALS['cookie_path'] : "/";
$this->session_cookie_domain = !empty($GLOBALS['cookie_domain']) ? $GLOBALS['cookie_domain'] : '';
$this->session_cookie_secure = !empty($GLOBALS['cookie_secure']) ? $GLOBALS['cookie_secure'] : false;
$this->session_name = $session_name;
$this->session_table = $session_table;
$this->session_data_table = $session_data_table;
$this->db = &$db;
$this->_ip = real_ip();
$this->_time = time();
$this->session_id = $session_id == '' && !empty($_COOKIE[$this->session_name]) ? $_COOKIE[$this->session_name] : $session_id;
if ($this->session_id) {
$tmp_session_id = substr($this->session_id, 0, 32);
if ($this->gen_session_key($tmp_session_id) == substr($this->session_id, 32)) {
$this->session_id = $tmp_session_id;
} else {
$this->session_id = '';
}
}
if ($this->session_id) {
$this->load_session();
} else {
$this->gen_session_id();
setcookie($this->session_name, $this->session_id . $this->gen_session_key($this->session_id), 0, $this->session_cookie_path, $this->session_cookie_domain, $this->session_cookie_secure);
}
register_shutdown_function(array(&$this, 'close_session'));
}
public function gen_session_id()
{
$this->session_id = md5(uniqid(mt_rand(), true));
return $this->insert_session();
}
public function gen_session_key($session_id)
{
static $ip = '';
if ($ip == '') {
$ip = substr($this->_ip, 0, strrpos($this->_ip, '.'));
}
return sprintf('%08x', crc32(ROOT_PATH . $ip . $session_id));
}
public function insert_session()
{
return $this->db->exec('INSERT INTO ' . $this->session_table . " (sesskey, expiry, ip, data) VALUES ('" . $this->session_id . "', '" . $this->_time . "', '" . $this->_ip . "', 'a:0:{}')");
}
public function load_session()
{
$session = $this->db->getOne('SELECT userid, adminid, user_name, user_rank, discount, email, data, expiry FROM ' . $this->session_table . " WHERE sesskey = '" . $this->session_id . "'");
if (empty($session)) {
$this->insert_session();
$this->session_expiry = 0;
$this->session_md5 = '40cd750bba9870f18aada2478b24840a';
$_SESSION = array();
} else {
if (!empty($session['data']) && $this->_time - $session['expiry'] <= $this->max_life_time) {
$this->session_expiry = $session['expiry'];
$this->session_md5 = md5($session['data']);
$_SESSION = unserialize($session['data']);
$_SESSION['user_id'] = $session['userid'];
$_SESSION['admin_id'] = $session['adminid'];
$_SESSION['user_name'] = $session['user_name'];
$_SESSION['user_rank'] = $session['user_rank'];
$_SESSION['discount'] = $session['discount'];
$_SESSION['email'] = $session['email'];
} else {
$session_data = $this->db->getOne('SELECT data, expiry FROM ' . $this->session_data_table . " WHERE sesskey = '" . $this->session_id . "'");
if (!empty($session_data['data']) && $this->_time - $session_data['expiry'] <= $this->max_life_time) {
$this->session_expiry = $session_data['expiry'];
$this->session_md5 = md5($session_data['data']);
$_SESSION = unserialize($session_data['data']);
$_SESSION['user_id'] = $session['userid'];
$_SESSION['admin_id'] = $session['adminid'];
$_SESSION['user_name'] = $session['user_name'];
$_SESSION['user_rank'] = $session['user_rank'];
$_SESSION['discount'] = $session['discount'];
$_SESSION['email'] = $session['email'];
} else {
$this->session_expiry = 0;
$this->session_md5 = '40cd750bba9870f18aada2478b24840a';
$_SESSION = array();
}
}
}
}
public function update_session()
{
$adminid = !empty($_SESSION['admin_id']) ? intval($_SESSION['admin_id']) : 0;
$userid = !empty($_SESSION['user_id']) ? intval($_SESSION['user_id']) : 0;
$user_name = !empty($_SESSION['user_name']) ? trim($_SESSION['user_name']) : 0;
$user_rank = !empty($_SESSION['user_rank']) ? intval($_SESSION['user_rank']) : 0;
$discount = !empty($_SESSION['discount']) ? round($_SESSION['discount'], 2) : 0;
$email = !empty($_SESSION['email']) ? trim($_SESSION['email']) : 0;
unset($_SESSION['admin_id']);
unset($_SESSION['user_id']);
unset($_SESSION['user_name']);
unset($_SESSION['user_rank']);
unset($_SESSION['discount']);
unset($_SESSION['email']);
$data = serialize($_SESSION);
$this->_time = time();
if ($this->session_md5 == md5($data) && $this->_time < $this->session_expiry + 10) {
return true;
}
$data = addslashes($data);
if (isset($data{255})) {
$this->db->autoReplace($this->session_data_table, array('sesskey' => $this->session_id, 'expiry' => $this->_time, 'data' => $data), array('expiry' => $this->_time, 'data' => $data));
$data = '';
}
return $this->db->exec('UPDATE ' . $this->session_table . " SET expiry = '" . $this->_time . "', ip = '" . $this->_ip . "', userid = '" . $userid . "', adminid = '" . $adminid . "', user_name='" . $user_name . "', user_rank='" . $user_rank . "', discount='" . $discount . "', email='" . $email . "', data = '$data' WHERE sesskey = '" . $this->session_id . "' LIMIT 1");
}
public function close_session()
{
$this->update_session();
if (mt_rand(0, 2) == 2) {
$this->db->query('DELETE FROM ' . $this->session_data_table . ' WHERE expiry < ' . ($this->_time - $this->max_life_time));
}
if ((time() % 2) == 0) {
return $this->db->query('DELETE FROM ' . $this->session_table . ' WHERE expiry < ' . ($this->_time - $this->max_life_time));
}
return true;
}
public function delete_spec_admin_session($adminid)
{
if (!empty($_SESSION['admin_id']) && $adminid) {
return $this->db->query('DELETE FROM ' . $this->session_table . " WHERE adminid = '$adminid'");
}
return false;
}
public function destroy_session()
{
$_SESSION = array();
setcookie($this->session_name, $this->session_id, 1, $this->session_cookie_path, $this->session_cookie_domain, $this->session_cookie_secure);
$this->db->query('DELETE FROM ' . $this->session_data_table . " WHERE sesskey = '" . $this->session_id . "' LIMIT 1");
return $this->db->query('DELETE FROM ' . $this->session_table . " WHERE sesskey = '" . $this->session_id . "' LIMIT 1");
}
public function get_session_id()
{
return $this->session_id;
}
public function get_users_count()
{
return $this->db->getOne('SELECT count(*) FROM ' . $this->session_table);
}
}
?>
db.php
<?php
class db{
protected $pdo;
public function __construct($dsn,$user,$pwd,$opt=''){
$this->pdo= new PDO($dsn,$user,$pwd,$opt);
}
public function getRow($sql, $limited = false){
$sql=$limited==true?trim($sql . ' LIMIT 1'):$sql;
$pdo_statement = $this->pdo->query($sql);
if($pdo_statement){
$res=$pdo_statement->fetchAll(PDO::FETCH_ASSOC);
if($limited) return $res[0];
return $res;
}
return false;
}
public function getOne($sql){
$sql=trim($sql . ' LIMIT 1');
$pdo_statement = $this->pdo->query($sql);
if($pdo_statement){
$res=$pdo_statement->fetch(PDO::FETCH_ASSOC);
return $res;
}
return false;
}
public function autoReplace($table, $field_values, $update_values, $where = '')
{
$field_descs = $this->getAll('DESC ' . $table);
$primary_keys = array();
foreach ($field_descs AS $value)
{
$field_names[] = $value['Field'];
if ($value['Key'] == 'PRI')
{
$primary_keys[] = $value['Field'];
}
}
$fields = $values = array();
foreach ($field_names AS $value)
{
if (array_key_exists($value, $field_values) == true)
{
$fields[] = $value;
$values[] = "'" . $field_values[$value] . "'";
}
}
$sets = array();
foreach ($update_values AS $key => $value)
{
if (array_key_exists($key, $field_values) == true)
{
if (is_int($value) || is_float($value))
{
$sets[] = $key . ' = ' . $key . ' + ' . $value;
}
else
{
$sets[] = $key . " = '" . $value . "'";
}
}
}
$sql = '';
if (empty($primary_keys))
{
if (!empty($fields))
{
$sql = 'INSERT INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')';
}
}
else
{
if (empty($where))
{
$where = array();
foreach ($primary_keys AS $value)
{
if (is_numeric($value))
{
$where[] = $value . ' = ' . $field_values[$value];
}
else
{
$where[] = $value . " = '" . $field_values[$value] . "'";
}
}
$where = implode(' AND ', $where);
}
if ($where && (!empty($sets) || !empty($fields)))
{
$count=$this->getOne("SELECT COUNT(*) as count FROM $table WHERE $where");
$count=$count['count'];
if (intval($count) > 0)
{
if (!empty($sets))
{
$sql = 'UPDATE ' . $table . ' SET ' . implode(', ', $sets) . ' WHERE ' . $where;
}
}
else
{
if (!empty($fields))
{
$sql = 'REPLACE INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')';
}
}
}
}
return $sql?$this->exec($sql):false;
}
public function getAll($sql)
{
$res = $this->pdo->query($sql);
if ($res !== false)
{
$arr = array();
while ($row = $res->fetch(PDO::FETCH_ASSOC))
{
$arr[] = $row;
}
return $arr;
}
return false;
}
public function __call($method,$args){
return call_user_func(array($this->pdo,$method),$args[0]);
}
}
fun.php
<?php
function real_ip()
{
static $realip = NULL;
if ($realip !== NULL) {
return $realip;
}
if (isset($_SERVER)) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
/* 取X-Forwarded-For中第一个非unknown的有效IP字符串 */
foreach ($arr AS $ip) {
$ip = trim($ip);
if ($ip != 'unknown') {
$realip = $ip;
break;
}
}
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$realip = $_SERVER['HTTP_CLIENT_IP'];
} else {
if (isset($_SERVER['REMOTE_ADDR'])) {
$realip = $_SERVER['REMOTE_ADDR'];
} else {
$realip = '0.0.0.0';
}
}
} else {
if (getenv('HTTP_X_FORWARDED_FOR')) {
$realip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('HTTP_CLIENT_IP')) {
$realip = getenv('HTTP_CLIENT_IP');
} else {
$realip = getenv('REMOTE_ADDR');
}
}
preg_match("/[\\d\\.]{7,15}/", $realip, $onlineip);
$realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';
return $realip;
}
init.php
<?php
define("ROOT_PATH",__DIR__);
include "db.php";
include "fun.php";
include "cls_session.php";
$dsn='mysql:dbname=test;host=127.0.0.1';
$user="root";
$passwd="";
$opt=array(
PDO :: ATTR_PERSISTENT => true
);
$db=new db($dsn,$user,$passwd,$opt);
$cls=new cls_session($db,'sessions',"sessions_data");
复制代码
下面是2个运行测试程序
set.php
<?php
include "init.php";
$_SESSION['a']="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajax";
//$_SESSION['b']="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajax11212312333333333333333333333333333333333333333333333333333333333333333";
//$_SESSION['c']="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajax11212312333333333333333333333333333333333333333333333333333333333333333";
//$_SESSION['d']="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajax11212312333333333333333333333333333333333333333333333333333333333333333";
//$_SESSION['e']="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajax11212312333333333333333333333333333333333333333333333333333333333333333";
//$_SESSION['f']="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajax11212312333333333333333333333333333333333333333333333333333333333333333";
//$_SESSION['g']="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajax11212312333333333333333333333333333333333333333333333333333333333333333";
$_SESSION['h']="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajax11212312333333333333333333333333333333333333333333333333333333333333333";
$_SESSION['i']="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajax11212312333333333333333333333333333333333333333333333333333333333333333";
unset($_SESSION['b']);
unset($_SESSION['c']);
unset($_SESSION['d']);
unset($_SESSION['e']);
unset($_SESSION['f']);
//unset($_SESSION['h']);
//unset($_SESSION['i']);
unset($_SESSION['g']);
var_dump($_SESSION);
复制代码
get.php
<?php
include "init.php";
var_dump($_SESSION);
最重要的是cls_session.php
session存库 有利于统计当前网站在线用户
因为ecshop至始至终没用session_start,session的存取还是和以前一样直接操作$_SESSION数组,所以,如果原来的session是存在文件里,现在可以不修改代码的使用这种方式
|
最近更新
常用插件
- ecshop没登陆情况下订单查
ecshop没登陆情况下订单查询插件,主要是针对ecshop在没有登陆的情况下...
- ecshop最小购买数量控制插
ecshop最小购买数量控制插件,这个插件主要是为我们提供一个十分方便...
- ecshop二次开发商品购买增
图片1香...
- ecshop2.7.1邮件发送插件
ecshop2.7.1邮件发送插件:该插件主要的开发思想是源于ecshop短信发送系统...
- ecshop2.7.2生成虚拟订单2.
以前我们开发过ecshop下的虚拟订单,就是客户在访问的时候,会自动生...
ecshop热门问答
ecshop热门资料
ecshop中秋
ecshop通用信息
ecshop邀请
ecshop显示超出
ecshop显示属性
ecshop时不时
ecshop后台界面模板
ecshop快乐
ecshop装箱单
ecshop社工
ecshopreleased
ecshopbug
ecshop销价
ecshop传功
ecshopGBDian
ecshop积分重复赠送
ecshop统计图标
ecshop一号店分类首页
ecshop成必选
ecshop评论列表
ecshop导航链接
ecshopvidoe
ecshop网站名
ecshopTNT
ecshopComsenzEXP
ecshopwhere
ecshop页面底部
ecshop彩色隐形眼镜
restful
ecshop都会