前一陣子才剛把整個session處理改寫
改成用memcache來處理session
寫完後才看到這個令人想吐血的東西
session.save_path string
Defines a comma separated of server urls to use for session storage, for example "tcp://host1:11211, tcp://host2:11211".
Each url may contain parameters which are applied to that server, they are the same as for the Memcache::addServer() method. For example "tcp://host1:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
不過既然都寫了,那就認命嘍。
順便分享一下花了一個下午的"成果"吧
自己寫程式的習慣,會把一些常用的東西寫成class
像session處理,不太喜歡直接呼叫session_start,session_destroy
原因很簡單,如果需要變動session架構,例如改用memcache或是使用DB 或檔案
修改程式碼可是非常頭痛的事情。
底下是自己寫的一個session處理的class
利用session_set_save_handler
重設session的處理函數
其中有個需要注意的地方就是$Shutdown->Add('session_write_close');
因為php本身有快取,所以session會在程式結束時才會寫回
可是一但session的write處理函數是在定義在一個class的成員函數時
會發生問題
php的物件在程式結束前會先呼叫destruct,然後才執行結束。
可是session的write是在物件都已經被消滅後才會呼叫
這時候就會產生問題
因此php5提供了一個session_write_close
將他註冊到shutdown function中
避免這個狀況
<?php
define('SESS_LIFTTIME', 3600);
define('MEMCACHE_HOST', 'xxxx');
define('MEMCACHE_PORT', 'xxxx');
define('SESS_PREFIX','xxxx');
define('SESSION_COMPRESSED',false);
class ShutdownClass
{
private $ShutdownFunctions;
function __construct(){$this->ShutdownFunctions=array();}
function Add($Proc) {return array_push($this->ShutdownFunctions,$Proc);}
function Proc()
{
foreach($this->ShutdownFunctions as $Index=>$Function)
{
if(is_array($Function))
$Function[0]->$Function[1]();
else
$Function();
}
}
}
$Shutdown=new ShutdownClass();
register_shutdown_function(array($Shutdown,'Proc'));
class SessionClass
{
private $Memcache=false;
private $SessionLifeTime;
function Open($SavePath='',$SessionName='')
{
if(!$this->Memcache) return false;
return true;
}
function Close()
{
return true;
}
function Read($ID)
{
if(!$this->Memcache) return false;
$ID=SESS_PREFIX.$ID;
return $this->Memcache->get($ID);
}
function Write($ID,$Data)
{
if(!$this->Memcache) return false;
$ID=SESS_PREFIX.$ID;
$this->Memcache->delete($ID);
return $this->Memcache->add($ID,$Data,SESSION_COMPRESSED,$this->SessionLifeTime);
}
function Gc($MaxLifeTime)
{
return true;
}
function __construct($LifeTime=false)
{
global $Shutdown;
if(!session_set_save_handler(
array(&$this,'Open'),array(&$this,'Close'),
array(&$this,'Read'),array(&$this,'Write'),
array(&$this,'Destroy'),array(&$this,'Gc')))
throw new Exception('Session start error:session_set_save_handler error');
$Shutdown->Add('session_write_close');
if($LifeTime===false)
$this->SessionLifeTime=SESS_LIFTTIME;
else
$this->SessionLifeTime=$LifeTime;
}
function __destruct()
{
if($this->Memcache) $this->Memcache->close();
}
function Start()
{
$this->Memcache=new Memcache();
if(!$this->Memcache->connect(MEMCACHE_HOST,MEMCACHE_PORT))
throw new Exception('Session start error:memcache error');
session_start();
}
function Destroy($ID=false)
{
if($ID===false) return true;
$ID=SESS_PREFIX.$ID;
$this->Memcache->delete($ID);
return true;
}
}
?>