저는 이전에 "Customizing SESSION(2) - 데이터베이스 저장"과 "내가 세션을 사용하지 않는 이유"라는 두 개의 글을 쓴 적이 있습니다.
그러나 나중에 문제가 있음이 밝혀졌습니다. 전자의 처리는 실제로 거의 쓸모가 없으며 세션 재활용을 별도로 처리해야 합니다. 후자는 데이터베이스를 자주 운영하여 큰 성능 문제를 일으킵니다.
지난 이틀 동안 신중한 검토 끝에 대략적인 계획이 제시됐지만 구체적이고 상세한 테스트는 이뤄지지 않았다.
1. 세션 처리와 통계를 결합합니다. 방문자도 기록됩니다.
2. 세션 기능을 시뮬레이션하기 위해 데이터베이스와 쿠키를 완전히 사용합니다.
3. 세션에서 사용자의 작업은 가능한 한 하나의 SQL 문으로 완료되어야 합니다. 세션이 필요하지 않은 경우에는 쿼리가 하나만 있습니다.
4. 효율성을 위해 세션 재활용은 통합되지 않으며, 인터페이스를 제공하고 이를 호출하여 구현할 수 있습니다.
코드는 자세한 설명 없이 일시적으로 제공됩니다.
SQL
테이블 생성 `*****_세션`(
`sid` char(32) NOT NULL,
`uid` int(10) NULL이 아닙니다.
`사용자 이름` char(32) NOT NULL,
`usertype`tinyint(1) NOT NULL,
`activetime` int(10) NOT NULL,
`expiry` int(10) NOT NULL,
`ip` char(15) NULL이 아닙니다.
`url` char(80) NOT NULL,
`값` char(255) NOT NULL,
기본 키(`sid`)
) 엔진=메모리 기본 문자 집합=utf8;
PHP 코드
<?
수업 세션{
private $_sessionPrex= '';//세션 접두사
개인 $_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;
}
공개 함수 시작(){
$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->세션[$key] = $value;
}또 다른{
$other = $this->세션['값'];
$other[$key] = $값;
$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);
}
}
공개 함수 파괴(){
$this->session['uid'] = 0;
$this->session['username'] = '';
$this->session['usertype'] = -1;
$this->session['expiry'] = $this->_expiry;
$this->session['value'] = 배열();
$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['value'] = 직렬화($dbSession['value']);
if(strlen($dbSession['value'])>255)$this->_error('session->값이 너무 깁니다!');
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);
사실을 반환;
}
개인 함수 _getSid(){
$sid = Strip_tags($_COOKIE[$this->_sessionPrex.'_sid']);
if(strlen($sid)==32){
if($this->_getSession($sid)){
사실을 반환;
}
}또 다른{
$sid = md5(time().mt_rand(1000,10000));
$this->_setCookie($this->_sessionPrex.'_sid',$sid);
}
$this->_setCookie($this->_sessionPrex.'_uid',0);
$this->세션 = 배열(
'uid' => 0,
'사용자 이름' => '',
'사용자 유형' => -1,
'활성 시간' => $this->_time,
'ip' => $this->_getip(),
'url' => Strip_tags($_SERVER['REQUEST_URI']),
'만료' =>$this->_expiry,
'값' => 배열()
);
$this->isNew = 1;
$this->session['sid'] = $sid;
}
개인 함수 _setCookie($name,$value,$expiry=0){
if(empty($expiry))$expiry = $this->_expiry;
if(빈($this->_domain)){
setcookie($name,$value,$this->_time + $expiry,'/');
}또 다른{
setcookie($name,$value,$this->_time + $expiry,'/',$this->_domain);
}
}
개인 함수 _getip(){
getip()을 반환합니다;
}
개인 함수 _setOptions($options){
foreach($key=>$value로서의 $옵션){
if(in_array($key,array('sessionPrex','time','model','expiry','domain'))){
$key = '_'.$key;
$this->$key = $값;
}
}
}
개인 함수 _error($msg){
새로운 Phpbean_Exception($msg)을 던져라;
}
}
?>
(이 코드는 직접 사용할 수 없습니다. 이 문서에서는 주로 아이디어를 제공합니다.)