以前に「SESSIONのカスタマイズ(2) - データベースの保存」と「Sessionを使わない理由」の2つの記事を書きました。
しかしその後、問題があることが判明した。前者の処理は実際にはほとんど役に立たず、セッションのリサイクルは個別に処理する必要があります。後者はデータベースを頻繁に操作するため、パフォーマンスに大きな問題が発生します。
過去2日間の慎重な検討の結果、大まかな計画は示されましたが、具体的で詳細なテストはありませんでした。
1. セッション処理と統計を組み合わせます。訪問者も記録されます。
2. データベースと Cookie を完全に使用して、セッション機能をシミュレートします。
3. セッションに対するユーザーの操作は、できる限り 1 つの SQL 文で完了する必要があります。セッションが必要ない場合、クエリは 1 つだけです。
4. 効率を高めるため、セッションのリサイクルは統合されていませんが、インターフェイスが提供されており、それを実装するために呼び出すことができます。
詳細な説明は省略し、暫定的なコードを示します。
SQL
CREATE TABLE `*****_session` (
`sid` char(32) NOT NULL、
`uid` int(10) NOT NULL、
`ユーザー名` 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、
`値` char(255) NOT NULL、
主キー (`sid`)
) エンジン = メモリ デフォルトの文字セット = utf8;
PHPコード
<?
授業セッション{
private $_sessionPrex= '';//セッションプレフィックス
private $_time = '';//現在時刻
private $_model = null //データベース操作モデル
private $_expiry = 1200;//セッションの有効期限
private $_domain = '';//セッションスコープ
protected $isNew = 0;//操作アクションを決定 0 更新 1 増加
protected $session = array();// 対応するセッション レコード
パブリック関数 __construct($options){
$this->_setOptions($options);
if(empty($this->_time))$this->_time = time();
$this->session['activetime'] = $this->_time;
}
パブリック関数 start(){
$this->_getSid();
}
パブリック関数セット($key,$value){
if(in_array($key,array('uid','username','usertype','url','expiry'))){
if($key == '有効期限'){
$this->_setCookie($this->_sessionPrex.'_sid',$this->session['sid'],$value);
$this->_setCookie($this->_sessionPrex.'_uid',$this->session['uid'],$value);
}
$this->session[$key] = $value;
}それ以外{
$other = $this->session['値'];
$other[$key] = $value;
$this->session['value'] = $other;
}
}
パブリック関数 get($key){
if(in_array($key,array('uid','username','usertype','url','expiry'))){
$this->セッション[$key]を返します;
}それ以外{
if(isset($this->session['value'][$key])){
return $this->session['value'][$key];
}
null を返します。
}
}
パブリック関数 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);
}
}
パブリック関数 destroy(){
$this->session['uid'] = 0;
$this->session['ユーザー名'] = '';
$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);
}
パブリック関数 __destruct(){
$this->_save();
}
プライベート関数 _save(){
$dbSession = $this->セッション;
$dbSession['値'] = シリアル化($dbSession['値']);
if(strlen($dbSession['value'])>255)$this->_error('session->value が長すぎます!');
if($this->isNew == 1){
//増加
$this->_model->insert($dbSession);
}それ以外{
//更新
$sid = $dbSession['sid'];
$this->_model->update(array_slice($dbSession,1),'sid=''.$sid.''');
}
}
プライベート関数 _getSession($sid){
$dbSession = $this->_model->detail('sid = ''.$sid.''');
if(!$dbSession) false を返す;
$dbSession['value'] = unserialize($dbSession['value']);
$this->session = array_merge($dbSession,$this->session);
true を返します。
}
プライベート関数 _getSid(){
$sid =strip_tags($_COOKIE[$this->_sessionPrex.'_sid']);
if(strlen($sid)==32){
if($this->_getSession($sid)){
true を返します。
}
}それ以外{
$sid = md5(time().mt_rand(1000,10000));
$this->_setCookie($this->_sessionPrex.'_sid',$sid);
}
$this->_setCookie($this->_sessionPrex.'_uid',0);
$this->session = array(
'uid' => 0、
'ユーザー名' => '',
'ユーザータイプ' => -1、
'activetime' => $this->_time,
'ip' => $this->_getip(),
'url' => ストリップタグ($_SERVER['REQUEST_URI']),
'有効期限' =>$this->_expiry,
'値' => 配列()
);
$this->isNew = 1;
$this->session['sid'] = $sid;
}
プライベート関数 _setCookie($name,$value,$expiry=0){
if(empty($expiry))$expiry = $this->_expiry;
if(empty($this->_domain)){
setcookie($name,$value,$this->_time + $expiry,'/');
}それ以外{
setcookie($name,$value,$this->_time + $expiry,'/',$this->_domain);
}
}
プライベート関数 _getip(){
getip() を返します。
}
プライベート関数 _setOptions($options){
foreach ($options as $key=>$value){
if(in_array($key,array('sessionPrex','time','model','expiry','domain'))){
$key = '_'.$key;
$this->$key = $value;
}
}
}
プライベート関数 _error($msg){
新しい Phpbean_Exception($msg) をスローします。
}
}
?>
(このコードは直接使用できないことに注意してください。この記事では主にアイデアを提供します)