您的位置:首页 > 编程语言 > PHP开发

php之自定义session存储机制【3】

2016-04-28 11:13 746 查看
session默认是以文件形式存储的,当网站的访问量很大的情况下,因为文件的IO性能问题,会让服务器的开销巨大,比较典型做法是把session存入数据库或内存,本文是以数据库为例。

主要有两个步骤:

1. 自定义实现session的操作方法,比如读、写、删除、垃圾回收…

2. 告诉系统的session机制调用自定义的方法去处理session.

数据库创建语句:

CREATE TABLE `t_session` (
`sess_id` varchar(50) NOT NULL COMMENT 'session id',
`sess_content` text NOT NULL COMMENT 'session内容',
`last_write` int(10) unsigned NOT NULL COMMENT '最后写入时间',
PRIMARY KEY (`sess_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8


代码如下:



session_db.php

<?php
require_once 'MyPdo.class.php';
require_once 'ModelFactory.class.php';
require_once 'SessionModel.class.php';

// function __autoload($class){
//     $filename = $class.".class.php";
//     if(file_exists($filename)){
//         require_once $filename;
//     }
// }

//让系统的session机制调用自定义的方法去处理session.
session_set_save_handler('sessionOpen', 'sessionClose', 'sessionRead', 'sessionWrite', 'sessionDestroy', 'sessionGc');

//打开session
function sessionOpen(){
echo "<br>sessionOpen";
}

//关闭session
function sessionClose(){
echo "<br>sessionClose";
return true;
}

//session根据id读取数据
function sessionRead($sess_id){
echo "<br>sessionRead";
$model = ModelFactory::M("SessionModel");
return $model->read($sess_id);
}

//session根据id写入数据
function sessionWrite($sess_id,$content){
echo "<br>sessionWrite";
$model = ModelFactory::M("SessionModel");
$model->write($sess_id,$content);
}

/**
* 销毁session,调用session_destroy()触发
* @param string $sess_id
*/
function sessionDestroy($sess_id){
echo "<br>sessionDestroy";
$model = ModelFactory::M("SessionModel");
$model->destroy($sess_id);
}

//垃圾session数据回收
function sessionGc($lifetime){
echo "<br>sessionGc";
$model = ModelFactory::M("SessionModel");
$model->gc($lifetime);
}

?>


MyPdo.class.php

<?php

class MyPdo
{

private static $_instance = null;

private $dbh;

private function __construct($config)
{
$dsn = "mysql:host={$config['host']}; port={$config['port']}; dbname={$config['dbname']}";
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => "set names {$config['charset']}"
);

try {
$this->dbh = new PDO($dsn, $config['username'], $config['passwd'], $options);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$this->dbh -> setAttribute ( PDO :: ATTR_ERRMODE ,  PDO :: ERRMODE_EXCEPTION );
}

private function __clone()
{}

public static function getInstance($config = array('host'=>'localhost','port'=>'3306','dbname'=>'db7','charset'=>'utf8','username'=>'root',"passwd"=>'root'))
{
return isset(self::$_instance) ? self::$_instance : (self::$_instance = new self($config));
}

public function getPdo(){
return $this->dbh;
}

public function close() {
$this->dbh = null;
self::$_instance = null;
}

public function query($sql) {
try {
$stmt =  $this->dbh->query($sql);
return $stmt;
} catch (PDOException $e) {
echo "<p>sql语句执行失败,请参考如下信息:</p>";
echo "<br>错误文件:" .$e->getFile();
echo "<br>错误行号:" .$e->getLine();
echo "<br>错误代号:" .$e->getCode();
echo "<br>错误信息:" .$e->getMessage();
echo "<br>错误语句:" .$sql;
}
}

public function exec($sql) {
try {
$num =  $this->dbh->exec($sql);//失败返回false,成功返回受影响的行数,也可能是0
if($num >= 0){
return true;
}
return $num;
} catch (PDOException $e) {
echo "<p>sql语句执行失败,请参考如下信息:</p>";
echo "<br>错误文件:" .$e->getFile();
echo "<br>错误行号:" .$e->getLine();
echo "<br>错误代号:" .$e->getCode();
echo "<br>错误信息:" .$e->getMessage();
echo "<br>错误语句:" .$sql;
}
}

/**
* 获取一行的结果
* @param string $sql
* @return array 数组
*/
public function fetchRow($sql){
$stmt = $this->query($sql);
return $stmt->fetch(PDO::FETCH_ASSOC);
}

/**
* 获取多行结果
* @param unknown $sql
* @return array 二维数组
*/
public function fetchAll($sql) {
$stmt = $this->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

/**
* 获取一个数据
* @param string $sql
* @return string
*/
public function fetchData($sql) {
$stmt = $this->query($sql);
$result =  $stmt->fetch(PDO::FETCH_NUM);
if($result){
return $result[0];
}
return '';
}

}

?>


ModelFactory.class.php

<?php

class ModelFactory
{
private static $arr = array();

static function M($class) {
if(!array_key_exists($class, static::$arr)){
static::$arr[$class] = new $class();
}
return static::$arr[$class];

}
}

?>


SessionModel.class.php

<?php
class SessionModel
{

/**
* 写入session_id的内容
* @param string $sess_id
* @param string $content
*/
public function write($sess_id,$content) {
$sql = "replace into t_session  (sess_id, sess_content, last_write) values ('$sess_id', '$content', UNIX_TIMESTAMP());";
return MyPdo::getInstance()->exec($sql);
}

/**
* 根据session_id读取内容
* @param string $sess_id
* @return string
*/
public function read($sess_id) {
$sql = "select sess_content from  t_session where sess_id = '$sess_id'";
return MyPdo::getInstance()->fetchData($sql);

}

/**
* 销毁session_id数据
* @param string $sess_id
*/
public function destroy($sess_id) {
$sql = "delete from t_session where sess_id = '$sess_id'";
return MyPdo::getInstance()->exec($sql);
}

/***
* gc垃圾回收删除超过有效期的session数据
* @param int $lifetime
* @return Ambigous <boolean, int>
*/
public function gc($lifetime){
$sql = "delete from t_session where last_write < (UNIX_TIMESTAMP()- $lifetime)";
return MyPdo::getInstance()->exec($sql);
}

}

?>


use_session_db.php

<?php
require 'session_db.php';

//每2次访问服务器,可能进行1次垃圾扫描回收
ini_set('session.gc_probability', '1');
ini_set('session.gc_divisor', '2');
//设置session的有效期10秒
ini_set('session.gc_maxlifetime', '10');
@session_start();

echo '<br>current session id= '.session_id();

echo '<br>';
print_r($_SESSION);

$_SESSION['name'] = 'jack';

$_SESSION['age'] = 60;

$_SESSION['city'] = 'guangzhou';

$_SESSION['age'] = 88;

// session_destroy();

echo "<br>I am the last code!!";




session_destroy() 会触发sessionDestroy(),并且马上关闭session

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: