세션을 DB에 저장해서 사용해 보죠.
이것은 어떤 장점이 있을까요?
본게시판의 alpastar님이 쓰신 '세션처리에 대한 생각(1)'을 읽어보시면 됩니다. ^^;
소스는 여러분이 이해하기 쉽게 클래스나 템플릿을 배제하였습니다.
조금만 손보시면 실무적으로도 사용가능 하다고 봅니다.
잘못된 점은, 다리 부러지지 않을정도로만 깊은 태클 해주세요.^^
1. 세션 핸들링 함수설명
우리가 해야할일은 6개의 open(), close(), read(), write(), destroy(), gc()
세션콘트롤 함수를 만들어야합니다.
그런다음 이 함수들을 다음함수로 등록 시킵니다.
session_set_save_handler( "open", "close", "read", "write", "destroy", "gc" );
이렇게 6개의 세션함수를 등록하면,
6개의 함수를 유저가 직접 호출해서 사용 하는것이 아니고, PHP가 적시적때에 알아서 호출하는 것입니다.
윈도우에서 callback 함수 같은 거죠.
그럼 언제 호출되는지 알아야 겠죠?
open() : session_start()함수가 시작되면서 호출된다고 생각하시면 됩니다.
우리는 디비를 이용하기때문에, 이곳에서 디비 연결작업을 합시다.
close() : 이것은 세션이 수행된 페이지가 닫힐때 호출된다고 생각하시면 됩니다.
우리는 디비를 닫으면되겠죠..혹은 그냥 암것도 안해도 됩니다.
read() : 이것은 물론 세션을 읽을때 사용되겠죠.
우리가 해야할일은 디비에서 값을 가져오는겁니다.
write() : 이것은 세션을 기록할때 호출됩니다.
우리는 디비에 저장해야겠죠.
destroy() : ssesion_unregister(), session_destroy()함수를 사용할때 호출된다고 생각하시면됩니다.
우리는 디비에서 해당 키값을 지워주면됩니다.
gc() : 이것은 가베지콜렉터...쓰레기값을 지워주는것입니다.
쓰레기값이라는것은 세션지속시간을 넘어가면 지워주는것이죠.
호출은 수시로 된다고 생각하시면 됩니다.
php.ini의 session.gc_probability 셋팅에 영향을 받습니다.
정확히는 session_start()가 시작될때, 그리고 세션값을 저장할때인session_register()에 호출됩니다.
일부 시스템에서 호출 안될때가 있습니다만, 그럴때는 강제호출도 가능합니다.
이것은 추후 또 얘기드리져.
참고로, 위 6개의 함수이름은 편하신데로 정하시면 됩니다.
2. 유저커스텀 세션함수를 만들고 등록시키자.
일단 세션이 저장될 테이블을 만들장~
CREATE TABLE session
(
sesskey char(32) not null, // 세션키
expiry int(11) unsigned not null, // 세션수명시간
value text not null, // 세션에 저장된값
PRIMARY KEY (sesskey)
);
다음은 소스 쫙~
<?php
// ========================================
// ============= 파일명 session.inc
// ============= 디비세션 고고고~
// ========================================
// 디비 핸들러를 전역변수로 선언
$DB_CONN = "";
// DB호스트이름, DB이름, DB사용자, DB패스워드
$DB_HOST = "localhost";
$DB_NAME = "mydb";
$DB_USER = "root";
$DB_PASS = "pass";
// 세션지속시간(세션이 살아있는 시간, 여기선 php.ini 설정값으로 함.
// 원하는 시간값(초단위)으로 넣어도됨 $SESS_LIFE = 1440; 이런식으로..
$SESS_LIFE = get_cfg_var( "session.gc_maxlifetime" );
// open()함수 : 디비에 연결작업
function sess_open( $save_path, $session_name )
{
global $DB_CONN, $DB_HOST, $DB_NAME, $DB_USER, $DB_PASS;
// 디비를 연결하쟈~
if ( !( $DB_CONN = mysql_connect( $DB_HOST, $DB_USER, $DB_PASS ) ) )
{
echo "디비에 연결할수 없엉 : ", mysql_error();
exit;
}
// DB를 선택
if ( !( mysql_select_db( $DB_NAME, $DB_CONN ) ) )
{
echo "디비가 안골라져~";
exit;
}
return true;
}
// close()함수 : 암것도 안한다~ 혹시나 디비를 닫아주고싶으면 여기서 한다.
function sess_close()
{
return true;
}
// read()함수 : $key에 해당되는, 저장된 세션값을 DB에서 가져오기
function sess_read( $key )
{
global $DB_CONN, $SESS_LIFE;
// 현재시간보다 세션지속시간이 크다면( 즉 세션이 살아있다면..) 불러온다
$sess_query = "SELECT value FROM session WHERE sesskey = '$key' AND expiry > " . time();
$sess_result = mysql_query( $sess_query, $DB_CONN );
if( list( $value ) = mysql_fetch_row( $sess_result ) )
{
return $value;
}
return false;
}
// write()함수 : $key세션에 $val값을 저장합니다. 즉 session_register()를 처리해준다
function sess_write( $key, $val )
{
global $DB_CONN, $SESS_LIFE;
// 현재시간에 세션지속시간을 더해준다
$expiry = time() + $SESS_LIFE;
$value = addslashes($val);
$sess_query = "INSERT INTO session ( sesskey, expiry, value ) VALUES ( '$key', $expiry, '$value' )";
$sess_result = mysql_query( $sess_query, $DB_CONN );
// 이미 세션이 저장되어있다면 세션지속시간을 더 늘려주고 값도 저장
if( !$sess_result )
{
$sess_query = "UPDATE session SET expiry = $expiry, value = '$value' WHERE sesskey = '$key' AND expiry > " . time();
$sess_result = mysql_query( $sess_query, $DB_CONN );
}
return $sess_result;
}
// destroy()함수 : $key에 해당하는 값을 지워주자. session_unregister()를 처리해준다.
function sess_destroy( $key )
{
global $DB_CONN;
$sess_query = "DELETE FROM session WHERE sesskey = '$key'";
$sess_result = mysql_query( $sess_query, $DB_CONN );
return $sess_result;
}
// gc()함수 : 세션지속시간이 현재시간보다 작은 쓰레기 세션들을 지워주자~
function sess_gc( $maxlifetime )
{
global $DB_CONN;
$sess_query = "DELETE FROM session WHERE expiry < " . time();
$sess_result = mysql_query( $sess_query, $DB_CONN );
return mysql_affected_rows( $DB_CONN );
}
// 우리가 작성한 여섯개의 함수를 등록하자~
session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
// 자 이제 세션을 스타트 시키자.
session_start();
// ========================================
// ============= session.inc 끝
// ========================================
?>
3. 사용예제
안좋은 형태의 소스입니다만, 이해를 위해서...^^;
<?php
// ========================================
// ============= 파일명 test.php
// ============= 디비세션 사용해볼까나~~
// ========================================
include "session.inc";
// 사용방법은 기존 세션과 똑같다.
// 저장은 디비로 된다. PHP는 알아서, 우리가 작성한 위의 6개의 함수를 호출한다.
// 디비에 어떤 형식으로 저장되는가는 스스로 살펴보시길
// 로그인 했는가?
if( !session_is_registered( "SESS_USER_ID" ) )
{
// 로그인 안함
if( !$protype )
{
echo
('
<form method="post" name="myform" action="test.php?protype=1">
아이디 : <input type="text" name="fid">
패스워드 :<input type="text" name="fpass">
<input type="button" value="확인" onclick="document.myform.submit()">
</form>
');
}
else
{
$SESS_USER_ID = $fid;
$SESS_USER_PASS = $fpass;
session_register( "SESS_USER_ID" );
session_register( "SESS_USER_PASS" );
echo( '<script laguage="javascript">location.href="./test.php"</script>' );
}
}
else
{
// 로그인 함
if( !$protype )
{
echo
("
<br>오케이 로그인 중이군~
<br>아이디 : $SESS_USER_ID
<br>패스워드 : $SESS_USER_PASS
<br><input type='button' value='로그아웃' onclick='location.href=\"./test.php?protype=1\"'>
");
}
else
{
session_destroy();
echo( '<script laguage="javascript">location.href="./test.php"</script>' );
}
}
// ========================================
// ============= test.php 끝
// ========================================
?>
4. 응용
이제 우리는 현재 접속자수를 쉽게 파악할 수 있습니다.
"SELECT count(sesskey) FROM session WHERE expiry > " . time()
이런식으로 쿼리를 주면 되겠죠..
또한 session테이블에 remote I.P.와 회원id등과같은 로그인 정보에대한
추가 항목을 삽입하여 접속자에대한 간단한 추적과 동일 id로의 로그인
차단등을 할수있습니다. |
|
|