这个类就是实现Session的功能,基本上是通过设置客户端的Cookie来保存SessionID,然后把用户的数据保存在服务器端,最后通过Cookie中的Session Id来确定一个数据是否是用户的,然后进行相应的数据操作。本方式适合Memcache内存方式存储Session数据的方式,同时如果构建分布式的Memcache服务器,能够保存相当多缓存数据,并且适合用户量比较多并发比较大的情况。

<?php
/*
 * 文件:    MemcacheSession.inc.php
 * 类名:    MemcacheSession Class
 * 功能:    自主实现基于Memcache存储的 Session 功能
 * 注意:    本类必须要求PHP安装了Memcache扩展或者必须有Memcache的PHP API
 *          获取Memcache扩展请访问: http://pecl.php.net
 */

//设定 SESSION 有效时间,单位是 秒
define('SESS_LIFTTIME', 3600);
define('DOMAIN', '.jiunile.com');

//定义memcache配置信息
define('MEMCACHE_HOST', 'localhost');
define('MEMCACHE_PORT', '11211');

if (!defined('MemcacheSession'))
{
	define('MemcacheSession', TRUE);
	class MemacheSession
	{
		//类成员属性定义
		static  $mSessSavePath;
		static  $mSessName;
		static  $mMemcacheObj;

		/*
		 * 构造函数
		 *
		 * @param string $login_user    登录用户
		 * @param int $login_type       用户类型
		 * @param string $login_sess    登录Session值
		 * @return Esession
	         */
		public function __construct()
		{
			//我的memcache是以php模块的方式编译进去的,可以直接调用
			//如果没有,就请自己包含 Memcache-client.php 文件
			if (!class_exists('Memcache') || !function_exists('memcache_connect'))
			{
				die('Fatal Error:Can not load Memcache extension!');
			}

			if (!empty(self::$mMemcacheObj) && is_object(self::$mMemcacheObj))
			{
				return false;
			}

			self::$mMemcacheObj = new Memcache;

			if (!self::$mMemcacheObj->connect(MEMCACHE_HOST , MEMCACHE_PORT))
			{
				die('Fatal Error: Can not connect to memcache host '. MEMCACHE_HOST .':'. MEMCACHE_PORT);
			}

			return TRUE;
		}

		/*
		 * sessOpen($pSavePath, $name)
	         * @param   String  $pSavePath
	         * @param   String  $pSessName
	         * @return  Bool    TRUE/FALSE
	         */
		public function sessOpen($pSavePath = '', $pSessName = '')
		{
			self::$mSessSavePath    = $pSavePath;
			self::$mSessName        = $pSessName;
			return TRUE;
		}

		/* 
	         * sessClose()
	         * @param   NULL
	         * @return  Bool    TRUE/FALSE
	         */
		public function sessClose()
		{
			return TRUE;
		}

		/*
	         * sessRead($wSessId)
	         * @param   String  $wSessId
	         * @return  Bool    TRUE/FALSE
	         */
		public function sessRead($wSessId = '')
		{
			$wData = self::$mMemcacheObj->get($wSessId);

			//先读数据,如果没有,就初始化一个
			if (!empty($wData))
			{
				return $wData;
			}
			else
			{
				//初始化一条空记录
				$ret = self::$mMemcacheObj->set($wSessId, '', 0, SESS_LIFTTIME);
				if (TRUE != $ret)
				{
					die("Fatal Error: Session ID $wSessId init failed!");
					return FALSE;
				}
				return TRUE;
			}
		}

		/*
		 * sessWrite($wSessId, $wData)
	         * @param   String  $wSessId
	         * @param   String  $wData
	         * @return  Bool    TRUE/FALSE
	         */
		public function sessWrite($wSessId = '', $wData = '')
		{
			$ret = self::$mMemcacheObj->replace($wSessId, $wData, 0, SESS_LIFTTIME);
			if (TRUE != $ret)
			{
				die("Fatal Error: SessionID $wSessId Save data failed!");
				return FALSE;
			}
			return TRUE;
		}

		/*
	         * sessDestroy($wSessId)
	         * @param   String  $wSessId
	         * @return  Bool    TRUE/FALSE
	         */
		public function sessDestroy($wSessId = '')
		{
			self::sessWrite($wSessId);
			return FALSE;
		}

		/*
	         * sessGc()
	         * @param   NULL
	         * @return  Bool    TRUE/FALSE
	         */
		public function sessGc()
		{
			//无需额外回收,memcache有自己的过期回收机制
			return TRUE;
		}

		/*
	         * initSess()
	         * @param   NULL
	         * @return  Bool    TRUE/FALSE
	         */
		public function initSess()
		{
			//不使用 GET/POST 变量方式
			ini_set('session.use_trans_sid',    0);

			//设置垃圾回收最大生存时间
			ini_set('session.gc_maxlifetime',   SESS_LIFTTIME);

			//使用 COOKIE 保存 SESSION ID 的方式
			ini_set('session.use_cookies',      1);
			ini_set('session.cookie_path',      '/');
			
			//多主机共享保存 SESSION ID 的 COOKIE
			ini_set('session.cookie_domain', DOMAIN);

			//将 session.save_handler 设置为 user,而不是默认的 files
			session_module_name('user');

			//定义 SESSION 各项操作所对应的方法名:
			session_set_save_handler(
				array('MemacheSession', 'sessOpen'),   //对应于静态方法 My_Sess::open(),下同。
				array('MemacheSession', 'sessClose'),
				array('MemacheSession', 'sessRead'),
				array('MemacheSession', 'sessWrite'),
				array('MemacheSession', 'sessDestroy'),
				array('MemacheSession', 'sessGc')
			);

			session_start();
			return TRUE;
		}
	}
}

$memSess = new MemacheSession;
$memSess->initSess();
?>

然后,在项目程序的头文件中直接包含 MemacheSession.inc.php 即可,并且以前的程序不用做任何改动。 测试 创建一个session。

<?php
//set_session.php
session_start();
if (!isset($_SESSION['admin'])) {
    $_SESSION['TEST'] = 'wan';
}
print $_SESSION['admin'];
print "/n";
print session_id();
?>

用 sessionid 去 memcached 里查询一下

<?php
//get_session.php
$mem = new Memcache;
$mem->connect("127.0.0.1", 11211);
var_dump($mem->get('0935216dbc0d721d629f89efb89affa6'));
?>

备注:memcache PECL 未来版本中,可以直接设置 php.ini 来这定自己的 session.save_handler,大致如下:

session.save_handler = memcache
session.save_path = "tcp://host:port?persistent=1&weight=2&timeout=2&retry_interval=15,tcp://host2:port2"