之前写过两篇文章自定义 SESSION(二) 数据库保存和我为什么不使用 session
但后来发现都有问题前者处理在实际中几乎没什么用处, 而且 session 回收还得自己另外处理后者频繁的操作数据库, 打来了很大的性能问题
这两天仔细考虑下, 大致给出一个方案, 但还没有具体详细的测试
1session 处理和统计结合起来同时游客也都有记录
2 完全使用数据库和 cookie 来模拟 session 的功能
3 用户的对 session 的操作都尽量保证在一条 sql 语句完成不用到 session 的时候, 绝对不多一条查询
4 为了效率起见, session 的回收没有集成进来, 但提供了接口, 可以调用实现
暂时给出代码, 不具体解释
- sql
- CREATE TABLE `*****_session` (
- `sid` char(32) NOT NULL,
- `uid` int(10) NOT NULL,
- `username` char(32) NOT NULL,
- `usertype` tinyint(1) NOT NULL,
- `activetime` int(10) NOT NULL,
- `expiry` int(10) NOT NULL,
- `ip` char(15) NOT NULL,
- `url` char(80) NOT NULL,
- `value` char(255) NOT NULL,
- PRIMARY KEY (`sid`)
- ) ENGINE=MEMORY DEFAULT CHARSET=utf8;
php 代码
- class session {
- private $_sessionPrex = ''; //session 的前缀
- private $_time = ''; // 当前时间
- private $_model = null; // 数据库操作模型
- private $_expiry = 1200; //session 有效时间
- private $_domain = ''; //session 的作用域
- protected $isNew = 0; // 判定操作动作 0 更新 1 增加
- protected $session = array(); // 对应的一条 session 记录
- public
- function __construct($options) {
- $this - >_setOptions($options);
- if (empty($this - >_time)) $this - >_time = time();
- $this - >session['activetime'] = $this - >_time;
- }
- public
- function start() {
- $this - >_getSid();
- }
- public
- function set($key, $value) {
- if (in_array($key, array('uid', 'username', 'usertype', 'url', 'expiry'))) {
- if ($key == 'expiry') {
- $this - >_setCookie($this - >_sessionPrex.'_sid', $this - >session['sid'], $value);
- $this - >_setCookie($this - >_sessionPrex.'_uid', $this - >session['uid'], $value);
- }
- $this - >session[$key] = $value;
- } else {
- $other = $this - >session['value'];
- $other[$key] = $value;
- $this - >session['value'] = $other;
- }
- }
- public
- function get($key) {
- if (in_array($key, array('uid', 'username', 'usertype', 'url', 'expiry'))) {
- return $this - >session[$key];
- } else {
- if (isset($this - >session['value'][$key])) {
- return $this - >session['value'][$key];
- }
- return null;
- }
- }
- public
- function gc($file, $time = 1200) {
- $lasttime = file_get_contents($file);
- if ($lasttime + $time < $this - >_time) {
- file_put_contents($file, $this - >_time);
- return $this - >_model - >delete('activetime+expiry<'.$this - >_time);
- }
- }
- public
- function destroy() {
- $this - >session['uid'] = 0;
- $this - >session['username'] = '';
- $this - >session['usertype'] = -1;
- $this - >session['expiry'] = $this - >_expiry;
- $this - >session['value'] = array();
- $this - >_setCookie($this - >_sessionPrex.'_sid', $this - >session['sid'], $this - >_expiry);
- $this - >_setCookie($this - >_sessionPrex.'_uid', $this - >session['uid'], $this - >_expiry);
- }
- public
- function __destruct() {
- $this - >_save();
- }
- private
- function _save() {
- $dbSession = $this - >session;
- $dbSession['value'] = serialize($dbSession['value']);
- if (strlen($dbSession['value']) > 255) $this - >_error('session->value is too long!');
- if ($this - >isNew == 1) {
- // 增加
- $this - >_model - >insert($dbSession);
- } else {
- // 更新
- $sid = $dbSession['sid'];
- $this - >_model - >update(array_slice($dbSession, 1), 'sid=\''.$sid.'\'');
- }
- }
- private
- function _getSession($sid) {
- $dbSession = $this - >_model - >detail('sid = \''.$sid.'\'');
- if (!$dbSession) return false;
- $dbSession['value'] = unserialize($dbSession['value']);
- $this - >session = array_merge($dbSession, $this - >session);
- return true;
- }
- private
- function _getSid() {
- $sid = strip_tags($_COOKIE[$this - >_sessionPrex.'_sid']);
- if (strlen($sid) == 32) {
- if ($this - >_getSession($sid)) {
- return true;
- }
- } else {
- $sid = md5(time().mt_rand(1000, 10000));
- $this - >_setCookie($this - >_sessionPrex.'_sid', $sid);
- }
- $this - >_setCookie($this - >_sessionPrex.'_uid', 0);
- $this - >session = array('uid' = >0, 'username' = >'', 'usertype' = >-1, 'activetime' = >$this - >_time, 'ip' = >$this - >_getip(), 'url' = >strip_tags($_SERVER['REQUEST_URI']), 'expiry' = >$this - >_expiry, 'value' = >array());
- $this - >isNew = 1;
- $this - >session['sid'] = $sid;
- }
- private
- function _setCookie($name, $value, $expiry = 0) {
- if (empty($expiry)) $expiry = $this - >_expiry;
- if (empty($this - >_domain)) {
- setcookie($name, $value, $this - >_time + $expiry, '/');
- } else {
- setcookie($name, $value, $this - >_time + $expiry, '/', $this - >_domain);
- }
- }
- private
- function _getip() {
- return getip();
- }
- private
- function _setOptions($options) {
- foreach($options as $key = >$value) {
- if (in_array($key, array('sessionPrex', 'time', 'model', 'expiry', 'domain'))) {
- $key = '_'.$key;
- $this - >$key = $value;
- }
- }
- }
- private
- function _error($msg) {
- throw new Phpbean_Exception($msg);
- }
- } ? >(注意, 该代码不能直接使用, 本文主要是提供一种思路)
来源: https://www.php1.cn/detail/php-e823a1c34f.html