클래스 구성
class.message.php : 에러 메시지 처리 클래스
class.mysql.php : MySQL 데이터베이스 관리 클래스
class.webpage.php : 웹페이지 관리 클래스
class.userglobal.php : 방문자공용변수 관리 클래스
PUBLIC 멤버함수
방문자공용변수 사용범위 지정자 관련 함수
[code php;gutter:false] function webpage_static_id($pageid="");
function webpage_member_id($pageid=""); [/code]
방문자공용변수 충돌 회피 관련 함수
[code php;gutter:false] function uglobal_lock();
function uglobal_unlock(); [/code]
방문자공용변수 처리(읽기, 쓰기, 삭제) 관련 함수
[code php;gutter:false] function uglobal($pageid, $name, $value="");
function uglobal_unset($pageid, $name); [/code]
예제 파일 구성
아래의 예제는 실제 홈페이지에 적용할 수 있는 완성된 프로그램이 아니고, 단지 웹애플리케이션 변수가 어떻게 동작하는지를 보여주기 위한 실험적인 프로그램이니 참고만 하세요.
class.message.php : 에러 메시지 처리 클래스
class.mysql.php : MySQL 데이터베이스 관리 클래스
class.webpage.php : 웹페이지 관리 클래스
class.userglobal.php : 방문자공용변수 관리 클래스

inc.baseinfo.php : 데이터베이스 호스트명, 사용자명, 비밀번호, 디비명을 얻기 위한 함수가 정의
common.php : 모든 페이지에서 공용으로 쓰이는 변수와 함수가 정의된 인클루드 파일
uglobal.php : 방문자공용변수 동작실험 시작 페이지
page1.php : 페이지 #1
page2.php : 페이지 #2
page3.php : 페이지 #3

Posted by 방글24
방문자공용변수란?
페이지 내에서 사용할 수 있는 변수를 사용범위(scope)를 가지고 분류하면 전역변수(global), 정적변수(static), 클래스의 데이터멤버(var), 지역변수 등이 있습니다. 이 중에 지역변수는 논외로 하고 나머지 전역변수, 정적변수, 데이터멤버는 페이지 내에서만 사용되는 변수(이하 "일반변수")들이며 따라서 다른 페이지로 이동되면 그 값이 소멸되기 때문에 페이지 상호간에 그 값이 전달, 유지되지 않습니다. 반면 방문자공용변수는 다른 페이지가 이동하더라도 그 값을 계속 유지된 상태로 사용할 수 있습니다.
다른 한편, 페이지에 접근하는 방문자 측면에서 볼 때의 변수의 사용범위를 살펴보면, 여러 방문자가 동일한 페이지에 접근하여 이 페이지에 있는 동일한 변수에 접근하더라도 각 방문자가 인식하는 변수는 서로 전혀 상관이 없습니다. 사용범위가 단일 방문자로 제한되지요. 이를 위한 변수가 세션변수인데 이에 대한 것은 PHP3에서도 이미 많이 다루어져 있고 PHP4에서는 기본 내장함수로 제공되고 있으므로 이를 이용하면 될 것입니다.
위에서 살펴본 바와 같이 현재의 일반변수는 그 사용범위가 단일페이지와 단일방문자로 정해져 있으며, 단일페이지 내에서도 그 값이 유지되지 않습니다. 따라서 웹 상에서 전체페이지, 전체방문자가 공유해야 하는 데이터를 다루기에는 적합하지 않습니다. 이러한 제한을 극복하고자 현재 다른 매체를 이용하여(파일, 공유메모리, 데이터베이스 등) 공유하고자 하는 데이터를 페이지 및 방문자 상호간에 주고받지요. 예를 들어 페이지에 접근하는 방문자수를 보여주기 위한 카운터를 보면, 이 카운터는 실제로는 단일페이지에서 사용하지만 전체방문자가 공유하는 데이터라고 할 수 있습니다.
이와 같이 전체 또는 복수페이지가 공유해야 하는 데이터는 아마 수도 없이 많이 있을 것입니다. 이는 사용범위가 전체 또는 복수페이지 확장할 수 있는 변수의 존재가 필요하다는 것을 의미하지요. ASP에서도 Application 객체를 가지고 모든 방문자들에게 읽히고 전체페이지에서 다루어지는 변수를 정의하여 사용할 수 있지요. 여기서는 좀더 발전하여 ASP Application에서 정의할 수 있는 전체페이지 & 전체방문자에 적용되는 변수뿐만 아니라 임의로 정하는 복수페이지, 단일페이지를 서로 혼합되어 적용할 수 있는 방문자공용변수를 정의하고, 선언하고, 사용하고, 삭제하기 위한 기능을 하는 함수를 클래스를 이용하여 작성하였습니다.
방문자공용변수 사용범위(scope)
방문자공용변수 사용범위 지정자에 지정할 수 있는 키워드에는 pageglobal, pagemember와 pagestatic이 있습니다.
pageglobal : 모든 웹페이지에서 사용하는 변수를 지정할 때 사용하는 지정자로 데이터베이스 테이블 pageid 필드에 "pageglobal" 라고 저장됩니다.
pagemember : 정해진 복수 페이지에서만 사용되는 변수를 생성하기 위한 지정자로 데이터베이스 테이블 pageid 필드에는 클래스 clsWebpage의 멤버함수인 webpage_member_id()로 지정된 현재 페이지의 멤버 ID가 저장됩니다.
pagestatic : 지정된 한 장의 웹페이지에서만 접근할 수 있는 변수를 지정할 때 사용하는 지정자로 데이터베이스 테이블 pageid 필드에는 클래스 clsWebpage의 멤버함수인 webpage_static_id()로 지정된 현재 페이지의 고유한 "페이지 ID"값이 저장됩니다.
방문자공용변수 값 유지관리 메커니즘
데이터베이스에 저장되어 있는 방문자공용변수들은 uglobal_lock() 멤버함수가 실행될 때 테이블로부터 그 값을 읽어들여 방문자공용변수값을 복원시킵니다. 반대로 uglobal_unlock() 멤버함수가 실행될 때 메모리 상에 데이터를 읽어 데이터베이스 테이블에 저장시킵니다.
방문자공용변수를 위한 데이터베이스 설계
방문자공용변수들은 페이지 이동에 관계없이 그 값을 계속 유지할 수 있어야 하는데, 값을 유지하기 위해 페이지 종료할 때 MySQL 데이터베이스의 정해진 테이블에 방문자공용변수 값을 저장한 후 다른 페이지를 읽어들일 때 데이터베이스 테이블로부터 저장된 값을 읽어 들여와 해당 방문자공용변수의 값을 원래대로 복원시켜줍니다. 이 때 사용되는 데이터베이스 테이블명이 저장된 데이터멤버에 접근할 수 멤버함수는 uglobal_db_table() 입니다. 테이블명의 초기 값은 "admin_uglobal"로 설정되어 있습니다. 그리고 테이블 스키마는 아래와 같습니다.
[code sql;gutter:false] CREATE TABLE 테이블명 (
pageid varchar(32) not null,
value blob not null,
PRIMARY KEY (pageid)
); [/code]
필드명 pageid : "pageglobal", "페이지 멤버 ID" 또는 "페이지 ID"가 저장됩니다.
필드명 value : 변수명과 변수 값이 저장됩니다.

Posted by 방글24
방문자공용변수 개요
MS의 ASP에서 사용되는 Application 객체에서와 같이 웹애플리케이션에서 모든 방문자가 데이터를 공유할 수 있는 변수를 등록하여 다룰 수 있도록 작성된 프로그램입니다.
웹애플리케이션?
웹애플리케이션은 웹 상에서 실행되는 파일들로 구성되며, 일반적으로 같은 디렉토리 상에 저장되어 있는 파일로 구성됩니다. 이러한 웹애플리케이션에서 동작되는 변수는 모든 사용자들이 공유하게 됩니다. 이와 같이 웹애플리케이션에서 동작되는 변수(이하 방문자공용변수)들은 여러 사람이 공유하다보니 단일 사용자만 사용하는 변수(정적변수, 전역변수, 세션변수 등)와는 다소 그 특성이 다르다고 할 수 있습니다.
방문자공용변수로 사용되는 가장 대표적인 경우가 카운터라고 할 수 있습니다. 현재 PHP에서 카운터를 구현할 때에 데이터베이스 테이블을 이용하거나 아니면 파일 액세스를 통해 그때그때 상황에 따라 개발하고 있어 다소 번거로운 면이 있다고 볼 수 있습니다. 만약 모든 사용자가 공유할 수 있는 방문자공용변수를 서버 사이드 스크립트인 PHP가 지원해 준다면 아주 간단히 카운터를 만들 수 있겠으나 그렇지 못한 것이 현실인 것 같습니다. 반면에 ASP에서는 Application 객체를 이용하면 카운터를 보다 간단히 구현할 수 있겠지요.
PHP에서도 모든 사람이 공유해야하는 데이터를 구현하기 위해 그때그때 번거롭게 데이터베이스나 파일을 다루기보다는 미리 방문자공용변수를 다룰 수 있는 라이브러리를 작성하여 이를 이용하면 어떨까 하는 생각에 방문자공용변수를 다룰 수 있는 함수를 클래스를 이용하여 만들어 보았습니다. 클래스 내부적으로는 방문자공용변수를 데이터베이스 테이블에 기록하고 필요에 따라 읽어들이고 있지요. 완벽한 기능을 가지지는 못했지만 좀 더 보완한다면 충분히 사용할 가치가 있다고 생각합니다.
방문자공용변수 충돌 회피의 필요성
방문자공용변수를 사용할 때는 한가지 주의할 점이 있는데, 방문자공용변수를 모든 방문자가 공유하다보니 이 변수를 한 방문자가 다루고 있는 순간에는 다른 방문자가 접근할 수 없도록 막아야 합니다. 그러지 않으면 방문자공용변수에 저장되는 데이터 결과를 전혀 신뢰할 수 없게 되지요.
카운터를 예를 들어보면, 이 카운터는 모든 방문자가 공유하게 됩니다. 한 방문자가 이 카운터를 읽어올 때 "100"이 저장되어 있었다면 이 값에 "1"을 더하여 카운터 값을 "101"로 수정하게 될 겁니다. 수정된 카운터 값을 저장하기 직전에 다른 방문자가 방문하여 카운터 값을 읽게 되면 아직 수정되기 전이기 때문에 "100"을 읽어들일 것이고 이 방문자도 "100"에 "1"을 더하여 카운터 값을 "101"로 수정하여 저장하려고 할 것입니다. 따라서 두 방문자가 모두 접근하더라도 카운터 값의 최종 결과는 "101"이 될 것이고 이 값은 실제 상황과 다른 신뢰할 수 없는 값이 되어 버릴 것입니다.
이런 현상을 방지하기 위해서는 방문자공용변수는 그 변수의 값을 다루기 전에 다른 방문자가 접근할 수 없도록 제한할 필요가 있고, 방문자공용변수를 더 이상 사용할 필요가 없을 때는 제한을 풀어주어 다른 사용자가 방문자공용변수를 사용할 수 있도록 할 필요가 있습니다. 이 역할을 수행하는 멤버함수가 uglobal_lock(), uglobal_unlock() 함수입니다.
[code php;gutter:false] .
.
.
$obj = new clsUserglobal($host, $user, $pass, $base);

$obj->uglobal_lock();

$all_page_hits = $obj->uglobal("pageglobal","all_page_hits")+1;
$obj->uglobal("pageglobal", "all_page_hits", $all_page_hits);

if (0 == ($all_page_hits % 10))
$history = "";
else
$history = $obj->uglobal("pageglobal", "history");

$history .= "[".$obj->webpage_static_id()
. "/히트수][a]=$all_page_hits";
$obj->uglobal("pageglobal", "history", $history);

$obj->uglobal_unlock();
.
.
. [/code]

Posted by 방글24
phpsource/데이터베이스2000. 11. 21. 17:54
미니디비 0.2.2p4
주로 인포믹스용 미니디비의 문제로 인해 업그레이드합니다. 이번에 수정한 내용들은 전부 내부적으로 처리되는 부분에 관한 것으로 사용자 인터페이스에는 전혀 변경이 없습니다.
  • PHP3를 지원하지 않습니다. class_exists 함수를 사용하기 때문에 4.0b4 이상에서만 정상적으로 동작합니다.
  • 디비 연결에 실패할 경우 에러메시지를 출력한 후 종료하도록 수정합니다. 이를 위해 클래스의 생성자를 수정합니다. 아래는 MySQL의 경우입니다.
[code php;gutter:false] function baseMysql($host="", $user="", $pass="", $base="", $connect="") {
if (is_array($host))
extract($host);

if (!$this->LID=$GLOBALS["_hBASE"]["mysql"]->connect($host, $user, $pass, $base, $connect))
die("Not a valid Link resource in ".__FILE__." on line ".__LINE__); // <-- 새로 추가된 에러출력 부분
} [/code]
미니디비 0.2.2p3
  • 스크립트 완료시 메모리 자원 해제 기능을 PHP 자체에서 처리하도록 하였습니다. 따라서 register_shutdown_function2 함수 및 소멸자를 모두 삭제하였습니다.
  • PHP 4.2.0 부터 포스트그레스 SQL의 함수명이 변경되었습니다. 따라서 포스트그레스용 미니디비가 PHP 버전에 따라 분리되었습니다.

    -class.pgsql.php(>= PHP 4.2.0)
    -class.pgsql-4.1.0.php(<= PHP 4.1.0)
미니디비 0.2.2p2
주로 인포믹스용 미니디비의 문제로 인해 업그레이드합니다. 이번에 수정한 내용들은 전부 내부적으로 처리되는 부분에 관한 것으로 사용자 인터페이스에는 전혀 변경이 없습니다.
  • 인포믹스용 미니디비 수정 내용

    -next_record()의 내용을 수정하였습니다.

    김기수 님이 지적하신 내용(보기싫은 에러 발생)에 따라 if (is_array($record=ifx_fetch_row($this->RID)))을 if (is_array($record=@ifx_fetch_row($this->RID))) 으로 수정합니다.

    -ifx_num_rows()함수에 문제가 있어 수정합니다.

    이 문제 역시 김기수 님이 지적하신 내용으로 자세한 내용은 Q&A 게시판에서 "[참고]미니디비 0.2.2p1 수정요망"라는 제목을 참조바랍니다.
    이 문제는 PHP에서 제공하는 ifx_num_rows() 함수가 정상적으로 동작하지 않는다는 것이었습니다. 말하자면 버그가 있는 함수라고 생각하시면 됩니다. 이 문제를 해결하기 위해 prvNumRows()를 아래와 같이 수정하였습니다.

  • 모든 미니디비에서 공통으로 수정된 내용

    - 소멸자(destructor)이 내용을 개선하였습니다.
    - init() 함수명을 connect() 로 변경하였습니다.
    - prvUnsetNumberIndex() 함수 처리에 있어 상황에 따라 약간의 문제가 발생하고 있어 수정하였습니다.
[code php;gutter:false] function prvNumRows($query) {
if (eregi("^[[:space:]]*SELECT[[:space:]]", $query)) {
$from_pos = strpos(strtoupper($query),"FROM");
$q = "SELECT count(*) ". substr($query, $from_pos);
$rid = @ifx_query($q, $this->LID);
$record = @ifx_fetch_row($rid);
@ifx_free_result($rid);
return $record['(count)'];
} else
return @ifx_affected_rows($this->RID);
} [/code]
미니디비 0.2.2p1
  • 데이터베이스용 세셔너핸들러와 충돌되어 수정하였습니다.

    따라서 데이터베이스용(공유메모리,파일,DBM/DBA,쿠키용은 관계없음) 세셔너핸들러를 사용하시는 분이 미니디비 0.2.2p1을 사용하기 위해서는 세셔너 0.2.5p1 과 데이터베이스용 세셔너핸들러 0.0.2p3를 함께 업그레이드 하여 주십시요.

    -미니디비 0.2.2p1
    -세셔너 0.2.5p1
    -데이터베이스용 세셔너핸들러 0.0.2p3

    동일한 웹문서에서 미니디비를 사용하는 복수의 라이브러리를 사용할 때는 아래와 같이 미니디비 파일을 가장 먼저 인클루드 시켜주세요.
[code php;gutter:false] require("./minidb/class.mysql.php"); // 미니디비(MySQL용) 0.2.2p1
require("./applicationer/class.applbase.php"); // 애플리케이셔너(디비용) 0.0.2
if ("3." == substr(phpversion(), 0, 2)) {
include("./sessioner/lib.sessioner.php"); // 세셔너 0.2.5p1
}
require("./sessioner/handler.sessbase.php"); // 세셔너핸들러(디비용) 0.0.2p3
require("./unittable/class.unittable.php"); // 유닛테이블 0.x.x [/code]
미니디비 0.2.2
  • 클래스 파일명이 class.디비명.inc에서 class.디비명.php로 변경되었습니다.
  • 클래스명이 baseDbsql에서 MiniDB로 변경되었습니다. (그러나 각 디비별로 정의된 클래스명은 먼저 그대로임)
  • 데이터베이스를 영구 접속할 것인지 임시 접속할 것인지를 선택할 수 있습니다.
  • MySQL 뿐만 아니라 모든 디비에서 REPLACE 쿼리문을 수행할 수 있습니다.
  • 스크립트 완료시 모든 불필요한 메모리 자원을 시스템에 자동 반환합니다.
    단, 스크립트가 중간에 비정상적으로 종료되었을 때의 문제는 남아 있습니다. 따라서 이런 문제로 발생하는 메모리 자원 반납은 시스템 차원에서 처리가 요망됩니다.
  • 동일한 데이터베이스 내에 존재하는 복수의 디비를 다룰 때의 문제점을 수정하였습니다.
  • 인포믹스 데이트베이스용을 추가하였습니다.
미니디비 0.2.1
  • 오라클용 미니디비의 버그 수정
  • DELETE, UPDATE, INSERT와 같은 쿼리문을 가지고 query() 함수를 실행할 때 affected rows를 반환하도록 개선
미니디비 0.2.0
  • 복수의 객체를 생성할 때 데이터베이스가 중복되어 연결되는 문제 해결
  • 서로 다른 데이터베이스를 동시에 작업할 수 있도록 개선
  • 정보은익(information hiding) 강화의 일환으로 멤버변수 접근 불허, 메소드만으로 접근
  • 메소드 인터페이스 변경
미니디비 0.1.2
  • PostgreSQL용 미니디비의 버그 수정
미니디비 0.1.1(최초 공개 버전)
  • MySQL, Oracle, SyBASE, MSQL, PostgreSQL, MSSQL용 DB Layer로 개발

'phpsource > 데이터베이스' 카테고리의 다른 글

{미니디비}4.사용방법  (0) 2000.11.21
{미니디비}3.사용자 인터페이스  (0) 2000.11.21
{미니디비}2.MiniDB 작성  (0) 2000.11.21
{미니디비}1.DB Layer의 필요성  (0) 2000.11.21
Posted by 방글24
phpsource/데이터베이스2000. 11. 21. 17:53
DB Layer로 사용할 때
여러가지의 데이터베이스를 동일한 방법으로 접근하는 방법으로 인클루드하는 파일만 바꿔주면 데이터베이스에 관계없이 접근합니다.
[code php;gutter:false] require("./minidb/class.mysql.php");
$db = new MiniDB("localhost", "userid", "password", "dbname");

if (list($rows,$fields)=$db->query("select * from Members")) {
while ($record=$db->next_record()) {
......
}
} [/code]
여러 개의 데이터베이스를 동시에 연결할 때
각 데이터베이스에 따라 별도로 정의된 클래스를 이용하여 객체를 생성합니다.
[code php;gutter:false] require("./minidb/class.oracle.php");
require("./minidb/class.mysql.php");

$mys = new baseMysql("localhost", "userid", "password", "dbname");
$ora = new baseOracle("localhost", "userid", "password", "ORCL");

if (list($rows,$fields)=$ora->query("select * from Members")) {
while ($record = $ora->next_record()) {
......
}
}

if (list($rows,$fields)=$mys->query("select * from Members")) {
while ($record = $mys->next_record()) {
......
}
} [/code]
복수의 디비명을 사용할 때
[code php;gutter:false] require("./minidb/class.mysql.php");

$my1 = new MiniDB("localhost", "userid", "password", "dbname#1");
$my2 = new MiniDB("localhost", "userid", "password", "dbname#2"); [/code]
동일한 데이터베이스를 가지고 여러 개의 객체를 생성할 때
문서가 여러개의 파일로 분리되어 있는 경우, 예를 들어 메인 스크립트에서 클래스로 작성된 문서를 불러들일 경우에 클래스 내에서 메인 스크립트와 관계없이 클래스 내에서 미니디비 클래스를 객체화 하여 사용할 수 있습니다. 이러한 경우에는 동일한 데이터베이스를 가지고 복수의 객체를 생성하게 될 것입니다. 제가 공개한 것 중에 미니디비를 이용하는 것이 많이 있는데 이러한 것이 현재는 거의 상속받아 처리하는 것으로 되어 있으나 아직 공개되지 않고 실험 중인 것은 대부분 클래스 내에서 별도로 객체화하여 사용하고 있습니다. 이럴 때 사용하는 방법으로 애플리케이셔너 0.0.2(미공개)의 경우를 예를 들어 보이겠습니다.
[code php;gutter:false] <?php /***메인 스크립트***/
require("./class.mysql.php"); // 미니디비(MySQL용) 0.2.2
require("./class.applbase.php"); // 애플리케이셔너(디비용) 0.2.0

$db = new MiniDB("디비 호스트명", "사용자명", "디비 패스워드", "디비명");

.
.
.
?>

<?php /***애플리케이셔너(디비용)***/
/*
filename : class.applbase.php (ver 0.0.2)
email : hwooky@phpclass.com
homepage : www.phpclass.com
author : hwooky
environment : PHP3 & 4, 미니디비 ver 0.2.2
*/

class Applicationer {
var $prvWaitingTime = 5; // Waiting Time(초단위)
var $prvResource = "Applicationer";
var $prvList = array();
var $baseClass = "MiniDB";
var $baseObj;

function Applicationer($resource="") {
if (!is_object($this->baseObj)) {
$base = $this->baseClass;
$this->baseObj = new $base;
}
if ($resource) $this->prvResource = $resource;
}

function prvLocking($varname) {
$query = sprintf("UPDATE %s SET islock=1,lastused=%s WHERE id='%s'",
$this->prvResource,
time(),
$varname
);
$this->baseObj->query($query);
}

.
.
.
?> [/code]
애플리케이셔너에서 $this->baseObj = new $base;을 보면 알겠지만 여기서는 메인 스크립트와 달리 아무런 인자도 없이 객체를 생성합니다. 이와 같이 두번째 객체를 생성할 때는 데이터베이스에 대한 정보가 필요없습니다.
단 하나의 레코드 중 하나의 필드 정보만을 얻고자 할 때
예를 들어, 쿼리된 레코드수를 구하는 예를 살펴보면 아래와 같습니다. 단, 이 방법은 PHP4에서만 적용됩니다.
[code php;gutter:false] if ($db->query("SELECT count(*) FROM $table")) {
list(,$count) = each($db->next_record());
}   [/code]
위의 예제를 PHP3에서 사용하려면 아래와 같이 수정합니다.
[code php;gutter:false] if ($db->query("SELECT count(*) FROM $table")) {
$rec = $db->next_record();
list(,$count) = each($rec);
} [/code]
데이터베이스에 접속하는 방법을 선택할 때
영구 접속할 때(초기 상태)
[code php;gutter:false] $db = new MiniDB("디비 호스트명", "사용자명", "디비 패스워드", "디비명", "pconnect"); [/code]
임시 접속할 때
[code php;gutter:false] $db = new MiniDB("디비 호스트명", "사용자명", "디비 패스워드", "디비명", "connect"); [/code]
게시판에서 제공하는 미니디비 압축 파일에 대한 참고사항
1. 소스코드에서 작성된 탭사이즈는 4컬럼입니다.
2. 첨부된 압축파일을 풀면 미니디비를 실험할 수 있는 예제가 세가지 있습니다.
1) DB Layer로 사용하기 위한 예제(dblayer.php3)
2) 복수의 디비명을 사용하기 위한 예제(mc.php3)
3) 다중 데이터베이스를 활용하기 위한 예제(mysql2oracle.php3)
"다중 데이터베이스를 활용하기 위한 예제"는 MySQL 데이터베이스에 있는 테이블의 모든 데이터를 오라클 데이터베이스에 있는 테이블로 이동시키는 예제입니다.
3. 예제를 실행할 때 필요한 테이블명과 디비명, 호스트명, 사용자명 및 비밀번호는 inc.db_info.php3에서 디비서버에 맞게 수정하세요.

Posted by 방글24
phpsource/데이터베이스2000. 11. 21. 17:51
ver 0.2.0부터는 사용자가 멤버변수에 접근할 수 없습니다. 따라서 ver 0.1.2에서 제공되던 멤버변수 $Host, $User, $Password, $Database는 생성자의 인자로 전달되며, $NumRows, $NumFields는 query() 함수의 리턴값으로 되돌려지며, $Record는 next_record() 함수의 리턴값으로 되돌려집니다.
메소드
내장된 메소드는 대부분 5개 정도로 작성되어 있으나 이 중에 사용자가 접근 가능한(public) 메소드는 단 2개에 불과합니다. SQL 쿼리 문을 수행하는 query() 메소드와 SELECT 쿼리 후 각 레코드를 읽어 올(fetch) next_record() 메소드입니다. 이 메소드명은 PHPLIB에서 사용하는 메소드명과 동일하나 리턴 값은 상이합니다. 데이터베이스에 접속하는 것과 이전에 쿼리하면서 사용된 메모리를 해제시키는 등의 작업은 내부적으로 알아서 수행해주기 때문에 사용자가 명시적으로 사용할 필요가 없습니다.
array query(string query_string);
이전 버전(ver 0.1.2)에서 제공하던 멤버변수 $NumRows, $NumFields이 query() 메소드의 리턴 값으로 받을 수 있습니다. 리턴 값의 데이터 형식은 배열로 배열의 첫번째 인자가 레코드수이고, 두번째 인자가 필드수입니다. 멤버변수 $NumRows, $NumFields는 더 이상 제공되지 않습니다.
DELETE, UPDATE, INSERT 쿼리문의 경우에는 리턴되는 레코드수는 affected rows를 의미합니다. 이 때 필드수는 의미없는 값입니다.
이전에 쿼리하면서 사용된 메모리가 있으면 메모리를 해제시키고, 입력된 쿼리문자열 $query_string을 DB에 보내 실행합니다. 마지막으로 쿼리에 해당하는 레코드의 수와 레코드에 포함된 필드수를 구합니다.
query() 함수의 사용방법은 아래와 같습니다.
[code php;gutter:false] if (list($rows,$fields)=$db->query("select * from Members")) {
// 정상적으로 쿼리되었을 때 처리할 내용
} else {
// 에러발생시 처리할 내용
} [/code]
레코드수와 필드수를 받을 필요가 없을 때는 if ($db->query("select * from Members")) 와 같이 코딩합니다.
리턴되는 두개의 값들은 query() 메소드를 수행하는 중에 설정되는 값으로, 레코드수는 SELECT 쿼리에서 얻어진 레코드 수를 나타내며, 필드수는 SELECT 쿼리에서 얻어진 필드항목 수를 나타냅니다. 해당되는 레코드 또는 필드항목수가 없으면 false으로 설정됩니다.
ver 0.2.2 부터는 모든 데이터베이스에서 "REPLACE" 쿼리문을 지원합니다. 이는 MySQL에서 제공하는 쿼리문 REPLACE과 같은 동작을 합니다. 즉, 같은 레코드가 있을 경우에는 이 레코드를 삭제한 후 INSERT 쿼리를 수행합니다. 같은 레코드가 없을 경우에는 INSERT 쿼리와 동일하게 동작합니다.
[code php;gutter:false] $db->query("REPLACE INTO (userid, password, age) VALUES ('user9', 'pw9', 22)"); [/code]
그러나 "REPLACE" 쿼리의 경우에는 MySQL을 제외한 다른 데이터베이스에서는 MySQL의 "REPLACE"처럼 완벽하게 동작하는 것은 아니고 몇가지 제한점이 있습니다. 우선 프라이머리 키는 하나만 허용합니다. 그리고 이 프라이머리 키는 field 배열을 첫번째 요소로 지정하여야 합니다. 위의 예에서 userid가 배열의 첫요소이며 따라서 이 필드명이 프라이머리키가 됩니다. 향후 버전에서는 프라이머리키 인식을 미니디비 내부에서 자동으로 감지하여야 할 것으로 생각되네요.
array next_record();
입력 값은 없습니다. next_record() 메소드를 수행하기 전에 반드시 query() 메소드를 수행하여야 합니다. 물론 query() 메소드에 입력된 쿼리문자열은 SELECT 쿼리 문일 때 next_record()를 사용할 수 있습니다. 현재 레코드 포인터에 해당하는 데이터베이스 테이블의 레코드 값을 읽어서 배열 형태로 되돌려줍니다. 만약 데이터베이스 테이블에 더 이상의 레코드가 없다면 false가 반환될 것입니다. 정상적으로 레코드 값이 읽혀져서 배열이 반환된다면 이 배열의 형태는 필드명에 의한 문자열 인덱스 배열(associative array; 연관배열, 연상배열)이 될 것입니다. 즉, 정수 인덱스 배열(scalar array)은 존재하지 않습니다. 만약 현재 레코드 포인터에 해당하는 레코드 값이 존재하지 않으면 false 값이 설정되어 있습니다. next_record() 메소드의 사용방법은 아래와 같습니다.
[code php;gutter:false] while ($record=$db->next_record()) {
......
} [/code]
사용방법이 이전과 동일합니다. 즉, 현재 레코드 포인터에 해당하는 데이터베이스 테이블의 레코드 값을 읽어서 배열 형태로 되돌려 줍니다. 이전 버전(ver 0.1.2)에서 제공되던 멤버변수 $Record는 더 이상 제공되지 않습니다.
생성자
디비 호스트명, 사용자 id, 디비 패스워드, 디비명을 생성자의 인자로 지정하여야 합니다. 이전 버전(ver 0.1.2)에서는 객체 생성 후 멤버변수에 직접 접근하여 설정하였으나 ver 0.2.0부터는 멤버변수가 제공되지 않습니다. 따라서 아래의 예와 같이 디비 정보를 생성자의 입력인자로 직접 지정하여야 합니다. ver 0.2.2부터는 클래스명이 baseDbsql에서 MiniDB로 변경되었으며 데이터베이스 접속방식을 지정할 수 있습니다.
[code php;gutter:false] $db = new MiniDB(
"디비 호스트명",
"사용자명",
"디비 패스워드",
"디비명",
"접속방식"
); [/code]
디비 정보를 위와 같이 별도로 지정할 수도 있지만 아래와 같이 배열을 통해 하나의 입력인자로 지정할 수도 있습니다.
[code php;gutter:false] $info = array(
"host"=>"디비 호스트명",
"user"=>"사용자명",
"pass"=>"디비 패스워드",
"base"=>"디비명",
"connect"=>"접속방식"
);

$db = new MiniDB($info); [/code]
객체를 복수로 생성할 경우에는 두번째 객체 생성할 때는 입력인자를 생략할 수 있습니다. 이와 같이 생략하면 데이터베이스를 새로이 연결하려고 시도하지 않고 이미 지정되어 있는 디비 정보에 의해 연결된 Link ID를 반환하게 됩니다.
[code php;gutter:false] $db = new MiniDB; [/code]
만약 디비명만을 변경하여 데이터베이스에 연결하려면 아래와 같이 디비명만 새롭게 지정하여 주면 됩니다.
[code php;gutter:false] $db = new MiniDB("새롭게 연결할 디비명"); [/code]
접속방식은 한번 지정되면 동일한 문서 내에서는 변경할 수 없습니다.
배열로 지정할 때는 각 배열의 키값을 반드시 위와 같이 "host", "user", "pass", "base", "connect"로 명시하여야 합니다.
그리고 배열 인자는 MiniDB 클래스명으로 접근할 때만 사용할 수 있으며, 각 데이터베이스별로만 사용되는 baseMsql, baseMssql, baseMysql, baseOci8, baseOracle, basePgsql, baseSybase로 객체를 생성할 때는 배열 인자를 지정할 수 없습니다. 이 때는 각 정보를 별도의 인자로 지정하기 바랍니다.
데이터베이스를 사용하기 위해서는 반드시 설정하여야 하는 값이나, 모두 사용되는 것은 아니며 사용하는 데이터베이스에 따라 설정하여야 하는 인자가 정하여져 있습니다. 데이터베이스에 따라 필요없는 인자는 빈문자열("")을 지정하여 주십시오. 각 데이터베이스에 따라 설정하여야 하는 인자는 아래와 같습니다.
DB
호스트명 사용자명 패스워드 디비명
MSQL 사용함 - - 사용함
MSSQL 사용함 사용함 사용함 사용함
MySQL 사용함 사용함 사용함 사용함
Oracle(OCI) - 사용함 사용함 사용함
Oracle(ORA) 사용함 사용함 사용함 사용함
PostgreSQL 사용함 - - 사용함
SyBASE 사용함 사용함 사용함 사용함
Informix 사용함 사용함 사용함 사용함
Oracle(ORA)의 경우에 원래 데이터베이스에서는 호스트명를 사용하지 않으나 Mini DB 내에서 서버가 웹서버와 동일한 곳에 위치하는지 아니면 다른 곳에 위치하는지에 따라 데이터베이스에 접속하는 방법이 다르기 때문에 이를 구분하기 위해 사용합니다. 이 때 동일한 곳에 위치하면 호스트명의 값을 "localhost"로 설정하여 주시고 아니면 "remotehost"로 설정하여 주십시오.
Informix의 경우에 localhost에 연결할 경우에는 호스트명으로 빈문자열을 지정하기 바랍니다.
생성자에서는 데이터베이스에 연결되어 있지 않으면 데이터베이스를 연결시키며, 데이터베이스 연결이 중복되어 연결되지 않도록 조절하는 기능이 포함되어 있습니다.
접속방식에는 "connect"와 "pconnect"를 지정할 수 있습니다. "connect"는 쿼리하는 동안에만 일시적으로 데이터베이스와 연결하는 방식이며, "pconnect"는 일단 데이터베이스와 연결된 후에는 일정시간동안 연결상태가 계속 유지되는 방식입니다. "connect"과 "pconnect"에는 각각 장단점이 있습니다. "pconnect"를 이용하는 것이 서버 부하를 줄일 수 있기는 하지만 일정 주기의 동시 사용자만큼의 프로세스가 필요하기 때문에 사용자가 많을 때는 이에 대한 별도의 대책이 필요합니다. "connect"는 쿼리를 실행할 때마다 매번 프로세스가 생성/소멸을 반복하기 때문에 프로세스 제한을 받지 않는 반면에 서버에 다소 부담이 될 수 있겠지요. 미니디비에서 접속방식을 지정하지 않으면 기본적으로 "pconnect"방식으로 연결됩니다. 그리고 한번 지정되면 다시 지정하지 않더라도 처음 지정된 접속방식이 계속 유지됩니다.
mysql_pconnect 를 실행하는 순간 DB 로 연결하는 process 가 하나 생성됩니다. 이 프로세스들은 보통 sleep 상태로 존재하다가 쿼리가 날라오면 active 상태가 되며 쿼리가 완료되면 sleep 이 됩니다. mysql_connect 같은 경우는 쿼리를 날리고 실행이 완료되면 프로세스 자체가 사라져 버리죠.
대신 mysql_pconnect 는 여러번 실행시켜도 이미 process 가 생성되었으면 또 다른 process가 생성되지 않습니다. 즉, 하나의 유저가 하나의 process 만 있으면 된단 뜻이죠. 이것을 써야 하는 이유는 수행효율 문제에 있습니다.
mysql_connect는 쿼리를 날릴때마다 매번 실행해야 하기 때문에 프로세스가 생성되고 해제되는 많은 시간이 소모됩니다. 반면, pconnect 는 한번 뜨면 끝입니다. 이런 이유로 pconnect 를 사용합니다. 보통 이것들은 일반적으로 8시간의 timeout 주기를 갖습니다. 즉, 유저가 DB 에 접속하고 나서 사용을 완전히 멈추고 난뒤 8시간이 지나야 이 프로세스가 사라집니다. 이건 분명히 문제입니다. 왜냐하면 MySQL 의 기본설정에서 프로세스 최대개수는 일반적으로 100개이기 때문입니다. 만약 100명의 사용자가 접속하여 100개의 프로세스가 떠 있다면 101번째 사용자는 DB 로 접근할 수 없다는 에러를 받게 됩니다.
connect와 pconnect에 관련된 자세한 내용은 관련 웹사이트를 검색하여 보시기 바랍니다.
예약어
예약된 전역변수
미니디비에서 내부적으로 사용하고 예약된 전역변수가 아래와 같이 있습니다.
$baseStaticMsql : Msql 데이터베이스 클래스에서 공용으로 사용하는 객체
$baseStaticMssql : Mssql 데이터베이스 클래스에서 공용으로 사용하는 객체
$baseStaticMysql : Mysql 데이터베이스 클래스에서 공용으로 사용하는 객체
$baseStaticOci8 : Oci8 데이터베이스 클래스에서 공용으로 사용하는 객체
$baseStaticOracle : Oracle 데이터베이스 클래스에서 공용으로 사용하는 객체
$baseStaticPgsql : Pgsql 데이터베이스 클래스에서 공용으로 사용하는 객체
$baseStaticSybase : Sybase 데이터베이스 클래스에서 공용으로 사용하는 객체
$baseStaticIfx : Infomix 데이터베이스 클래스에서 공용으로 사용하는 객체

$baseFlag : 클래스 MiniDB 정의를 한번만 인클루드하도록 해주는 플래그
예약된 클래스명
미니디비에서 클래스를 정의할 때 사용하고 클래스명들은 아래와 같습니다.
baseStaticMsql : Msql 데이터베이스 클래스에서 공용으로 사용하는 클래스
baseStaticMssql : Mssql 데이터베이스 클래스에서 공용으로 사용하는 클래스
baseStaticMysql : Mysql 데이터베이스 클래스에서 공용으로 사용하는 클래스
baseStaticOci8 : Oci8 데이터베이스 클래스에서 공용으로 사용하는 클래스
baseStaticOracle : Oracle 데이터베이스 클래스에서 공용으로 사용하는 클래스
baseStaticPgsql : Pgsql 데이터베이스 클래스에서 공용으로 사용하는 클래스
baseStaticSybase : Sybase 데이터베이스 클래스에서 공용으로 사용하는 클래스
baseStaticIfx : Infomix 데이터베이스 클래스에서 공용으로 사용하는 클래스

baseMsql : MSQL 데이터베이스를 사용하기 위해 작성된 클래스
baseMssql : MSSQL 데이터베이스를 사용하기 위해 작성된 클래스
baseMysql : MYSQL 데이터베이스를 사용하기 위해 작성된 클래스
baseOci8 : OCI8 데이터베이스를 사용하기 위해 작성된 클래스
baseOracle : ORACLE 데이터베이스를 사용하기 위해 작성된 클래스
basePgsql : PGSQL 데이터베이스를 사용하기 위해 작성된 클래스
baseSybase : SYBASE 데이터베이스를 사용하기 위해 작성된 클래스

MiniDB : 미니디비를 DB Layer로 사용하기 위해 정의된 클래스명
예약된 함수명
미니디비에서 클래스를 정의할 때 사용하고 클래스명들은 아래와 같습니다.
baseDestrMsql() : baseMsql 데이터베이스 클래스의 소멸자를 실행하기 위한 함수
baseDestrMssql() : baseMssql 데이터베이스 클래스의 소멸자를 실행하기 위한 함수
baseDestrMysql() : baseMysql 데이터베이스 클래스의 소멸자를 실행하기 위한 함수
baseDestrOci8() : baseOci8 데이터베이스 클래스의 소멸자를 실행하기 위한 함수
baseDestrOracle() : baseOracle 데이터베이스 클래스의 소멸자를 실행하기 위한 함수
baseDestrPgsql() : basePgsql 데이터베이스 클래스의 소멸자를 실행하기 위한 함수
baseDestrSybase() : baseSybase 데이터베이스 클래스의 소멸자를 실행하기 위한 함수
baseDestrIfx() : baseIfx 데이터베이스 클래스의 소멸자를 실행하기 위한 함수

'phpsource > 데이터베이스' 카테고리의 다른 글

{미니디비}5.업그레이드 및 패치  (0) 2000.11.21
{미니디비}4.사용방법  (0) 2000.11.21
{미니디비}2.MiniDB 작성  (0) 2000.11.21
{미니디비}1.DB Layer의 필요성  (0) 2000.11.21
Posted by 방글24
phpsource/데이터베이스2000. 11. 21. 17:45
Mini DB를 제작하게된 동기는?
앞서 공개된 유닛테이블의 최초버전(ver 0.10)이 MySQL 전용으로 작성되었는데 이것을 본 방문자 중에 유닛테이블을 오라클에서 사용할 수 있느냐는 질문과 DB Layer를 만들어 보면 어떻겠느냐고 질문하시는 것을 보고 DB Layer의 필요성을 느꼈지요. 그래서 임시로 PHPLIB에 있는 DB Layer를 이용한 PHPLIB 버전(ver 0.11)을 공개하게 되었습니다. 그런데 기존의 DB Layer들(PHPLIB, phpDB, Metabase 등)은 데이터베이스를 다루는데 필요한 많은 기능을 구현하다보니 덩치가 큰 편이지요. 이러다 보니 유닛테이블의 PHPLIB 버전의 경우를 보면 배보다 배꼽이 커진 결과가 되었지요. 그래서 데이터베이스를 다루는데 꼭 필요한 쿼리(query) 기능과 레코드를 읽어 오는 페치(fetch) 기능만을 가진 초경량급 DB Layer를 제작하게 되었습니다.
각 DB Layer의 파일 크기 비교(단위:KB)
DB
Metabase
2000.7.5
phpDB
102bR6
PHPLIB
7.2
Mini DB
0.1.1
Mini DB
0.2.2p1
MSQL 9.07 14.9 3.23 1.32 3.98
MSSQL 12.8 15.1 3.47 1.33 4.02
MySQL 10.8 15.0 9.74 1.33 3.85
Oracle(OCI) 17.1 - 7.61 1.54 4.12
Oracle(ORA) - - 13.1 1.76 4.37
ODBC 8.31 - 4.32 - -
PostgreSQL 9.73 15.2 3.74 1.50 4.02
SyBASE - 15.1 3.04 1.34 4.05
Informix - - - - 3.88
Metabase의 경우에는 각 데이터베이스 관련 파일 외에도 공통으로 사용되는 파일이 반드시 포함되어야 하는데 이 파일크기가 12.8KB입니다. 추가로 필요한 파일이지요. Mini DB 0.1.1의 경우에는 별로 사용되지 않는 기능은 모두 삭제하였기 때문에 다른 것에 비해 파일 크기가 작습니다만 대부분의 홈페이지에서 다루는 게시판 또는 방명록에서 다루는 정도에는 전혀 지장이 없을 것으로 생각됩니다. 내장된 메소드에 대하여는 다음 장에서 살펴보겠습니다.
지원되는 데이터베이스 및 파일 구성
위에 있는 표에서 보듯이 Mini DB가 지원하는 데이터베이스는 7개로 MSQL, MSSQL, MySQL, Oracle(OCI), Oracle(ORA), PostgreSQL, SyBASE, Informix입니다.
각 데이터베이스에 대한 클래스가 정의되어 있는 파일은 아래와 같습니다.
MSQL - class.msql.php
MSSQL - class.mssql.php
MySQL - class.mysql.php
Oracle(OCI) - class.oci8.php
Oracle(ORA) - class.oracle.php
PostgreSQL - class.pgsql.php
Sybase - class.sybase.php
Informix - class.ifx.php
양해 사항
미니디비 0.1.1 테스트
유닛테이블을 공개하면서도 양해를 구한 내용입니다만, 현재 제 서버에는 MySQL(3.22.32)과 오라클(8.0.5) 만 설치되어 있어서 다른 데이터베이스에 대하여는 테스트를 할 수가 없습니다. 그래서 다른 DB Layer와 매뉴얼만 보고 작성하다보니 소스코드 내에 버그가 숨어있을 것 같은데 알 수가 없습니다. 혹시 여러분이 사용하시다가 이상한 것이 있으면 알려주세요. 사실 Mini DB를 제작하기 전에는 MySQL 밖에 설치되어 있지 않았었는데 나름대로 DB Layer를 만들려다 보니 다른 것은 몰라도 오라클만큼은 테스트하지 않을 수 없었습니다. 그래서 이번 기회에 제 서버에 오라클을 설치해 봤습니다. 앞으로 시간이 허락되고 서버가 충돌만 일으키지 않는다면 PostgreSQL과 SyBASE 까지는 설치하여 Mini DB를 테스트해 볼 생각입니다.
미니디비 0.1.1 중 PostgreSQL 테스트 추가 실시(2000.9.29)
PostgreSQL 7.0.2를 제 서버에 설치하여 Mini DB를 테스트를 하여보니 약간의 에러가 있어 class.pgsql.php 클래스 파일을 수정하였습니다. pg_pconnect()의 인자를 PostgreSQL 버전6.3 이후부터 지원하기 시작하는 domain 이름을 사용할 수 있도록 내부 메소드를 수정하였습니다. 따라서 생성자 인자로 전달하여야 하는 데이터베이스 정보로는 호스트명과 디비명만을 사용합니다. domain이름을 사용하기 위해서는 데몬 로드시 반드시 -i 옵션을 주고 로드 하여야 합니다.(예: postmaster -i &)
미니디비 0.2.2p1 테스트(2001.5.31)
미니디비 0.2.2p1의 테스트는 오라클(8.0.5), MySQL(3.22.32), PostgreSQL(7.0.2)에서만 실시하였습니다. 제 서버 사정상 이 외의 데이터베이스에 대하여는 문서상으로만 보고 만들어서 테스트는 못하였네요. 혹시 이 부분에 대하여 테스트한 결과가 있으면 알려주세요.

Posted by 방글24
phpsource/데이터베이스2000. 11. 21. 17:44
DB Layer는 여러 가지의 데이터베이스(MySQL, Oracle, SyBASE, MSQL, PostgreSQL, ...... )를 동일한 방법으로 다룰 수 있도록 애플리케이션과 데이터베이스 중간에 놓여지게 됩니다. 이러한 DB Layer로써 동작하도록 제작된 Mini DB를 공개합니다. 기존에 공개되고 있는 유명한 DB Layer에 대하여 궁금하면 하단에 있는 웹사이트를 방문해 보세요.
ver 0.2.0부터는 복수의 데이터베이스를 동시에 다룰 수 있도록 수정하였습니다. DB Layer로도 계속 사용할 수 있으며 양 쪽을 혼합하여 사용할 수도 있습니다.
DB Layer의 필요성
만약 사용자가 MySQL과 같은 특정 데이터베이스만 다루게 된다면 DB Layer와 같은 DB를 위한 중간계층은 필요 없을 것입니다. 그러나 여러분이 프로로 활동하고 있다면 언제 어떤 데이터베이스를 다룰지는 모르는 일입니다. 나중에 데이터베이스를 바꾸게 되었을 때 기존에 특정 데이터베이스에 맞게 작성된 코드를 새로운 데이터베이스에 맞게 바꾼다고 생각해 보세요. 간단한 소스라면 별문제 없겠지만 조금만 복잡한 코드라면 아마 고생 꽤나 해야 할 것입니다. 새로운 데이터베이스를 구동시키는 함수를 배우기도 쉽지 않겠지요. 새로운 데이터베이스에 대한 함수를 배우는 게 별거 아니라고요? 사실 데이터베이스에 관련된 PHP 함수를 보면 서로 비슷비슷한 것도 많이 있기도 해요. 그러나 오라클 함수와 MySQL 함수를 비교해 보세요. MySQL 데이터베이스만 다루던 사람이 오라클 함수를 대하게 되면 아마 머리가 흔들흔들할 것입니다. 이럴 때 PHPLIB 또는 phpDB와 같은 layer가 있으면 너무나 간단히 해결되지요. 원하는 데이터베이스로 작성된 클래스 파일로 교체해 주면 되거든요. 이와 같이 여러 개의 데이터베이스를 다루어야 하는 경우에 꼭 필요한 것이 "DB layer"입니다.
DB Layer를 사용하지 않을 때
< DB Layer를 사용하지 않을 때 >
DB Layer를 사용하지 않고 각 데이터베이스를 애플리케이션에서 사용하기 위해서는 각 데이터베이스에 맞는 PHP 함수를 사용하여야 합니다. 따라서 동일한 기능을 수행하는 애플리케이션이라 하더라도 데이터베이스가 변경되면 애플리케이션의 소스코드도 이에 따라 변경되어야 합니다.
DB Layer를 사용했을 때
< DB Layer를 사용했을 때 >
그러나 데이터베이스와 애플리케이션 사이에 DB Layer를 사용하게 되면 각 데이터베이스에 따라서 다르게 코딩해야 하는 부분을 DB Layer가 흡수해 버리기 때문에 애플리케이션에서는 데이터베이스와 관계없이 독립적으로 코딩을 할 수 있게 됩니다. 중, 대형 프로젝트를 수행할 때는 꼭 필요한 기능이라고 할 수 있지요.

Posted by 방글24
phpsource/회원인증2000. 11. 21. 14:16

특정 회원만 사용할 수 있는 인증페이지를 작성하는 방법에 대한 예제입니다.
이 예제는 이전의 "세션라이브러리 예제"와 동일한 예제로, 변경된 것은 세션 라이브러리 대신에 세셔너클래스를 사용하여 세션 관리를 합니다. 인터페이스는 거의 동일합니다. 소스 코드는 대폭적으로 수정하였습니다.
회원 정보 테이블의 구조(MySQL의 경우)
[code sql;gutter:false] CREATE TABLE Members ( userid varchar(20) not null PRIMARY KEY, password varchar(16) not null ); [/code]
회원 정보 테이블에 저장된 회원 정보(MySQL의 경우)
이전 버전에서 사용하던 회원 정보가 변경되었습니다. 각 회원 정보를 아래와 같이 다시 생성해 주십시요.
userid password
user1 test
user2 test
user3 test
[code sql;gutter:false] INSERT INTO Members VALUES('user1', 'test'); INSERT INTO Members VALUES('user2', 'test'); INSERT INTO Members VALUES('user3', 'test'); [/code]
웹사이트 구성도
< 웹사이트 구성도 >
홈페이지에서 로그인 정보(사용자 ID, 비밀번호)를 입력합니다. 로그인 정보를 전송받은 웹서버는 회원 정보 테이블에 저장된 회원 정보와 비교하여 회원임이 판명되면 회원인증ID를 발급하고, 회원이 아니라면 다시 로그인 정보를 입력하도록 요구합니다. 이 프로그램에서 $access_userid에 로그인 할 때 입력된 사용자 ID를 설정하는 것으로 회원인증ID를 발급합니다. 회원 전용 페이지(페이지 #1, #2, #3, #4)에서는 $access_userid를 확인함으로써 로그인 과정을 거친 회원임을 알 수 있으며 따라서 별도의 인증 과정없이 회원 전용 서비스를 제공하게 됩니다.
회원 전용 페이지 서두에는 현재 페이지의 퍼미션 등급과 퍼미션 회원ID를 아래와 같이 설정합니다.
[code php;gutter:false] $permission_user = "user1"; $permission_type = "owner"; [/code]
위와 같이 $permission_type에 "owner"을 설정하면 특정 회원에게만 제공되는 페이지로 이 때는 반드시 $permission_user에 회원ID를 지정하여야 합니다. 위와 같은 경우는 회원ID가 "user1"인 회원에게만 허용된 페이지입니다. 만약 로그인에 성공한 모든 회원에게 페이지 접급을 허용하려면 아래와 같이 $permission_type에 "login"을 설정하면 됩니다. 이 때는 $permission_user를 지정할 필요가 없습니다.
[code php;gutter:false] $permission_type = "login"; [/code]
페이지 구성 및 회원별 접근 제한
예제 프로그램에서는 페이지 #1, #2, #3는 퍼미션 등급이 "owner"으로 설정되어 있고, 페이지 #4는 "login"으로 설정되어 있습니다.
페이지 구성 접근이 허용된 회원
홈페이지
(로그인 정보 입력)
모든 방문자
페이지 #1 로그인한 "user1" 회원
페이지 #2 로그인한 "user2" 회원
페이지 #3 로그인한 "user3" 회원
페이지 #4 로그인한 모든 회원
예제 #1과 예제 #2
예제 #1은 로그인후에 오른쪽에 사용자목록이 나타나고 이 목록에서 사용자페이지를 선택할 수 있습니다. 반면 예제 #2는 사용자목록 없이 로그인 하면 바로 자신의 페이지로 넘어가도록 하였습니다. 예제 #2는 원하시는 분이 있어 추가하였습니다. 소스는 Tip&Tech&Download 게시판에 등록되어 있습니다.
버전 0.2.0에서는 세셔너함수 0.2.1을 이용하여 작성되었습니다. 세셔너함수를 인클루드하는 부분만 삭제하면 PHP4의 세션함수를 이용하여 동작합니다.

Posted by 방글24
클래스 구성
- class.string.php : 문자 처리 클래스
- class.htmltagext.php : HTML 태그 처리 클래스
- class.sessionclient.php : 서버 & 클라이언트 세션 관리 클래스
PUBLIC 멤버함수
클래스를 이용하여 작성되었으며 사용되는 멤버함수는 아래와 같습니다.
- ses_start()
- ses_register()
- ses_unregister()
- ses_destory()

- tagext_head()
- tagext_body()
- submit_anchor()
ses_start() 함수는 세션기능을 시작하는 함수로 클래스의 생성자로 자동 수행하므로 사용자가 임의로 수행할 필요는 없습니다.
ses_register() 함수는 서버 사이드 또는 클라이언트 사이드 또는 양쪽 모두에서 사용하기를 바라는 세션변수를 등록하기 위한 함수입니다.
ses_unregister() 함수는 더 이상 사용되지 않는 세션 변수를 삭제합니다.
ses_destory() 함수는 세션을 강제로 종료하기 위한 함수입니다.
세션 관련 함수는 이미 나온 PHP3용 세션 라이브러리 또는 PHP4 세션 함수의 기능과 거의 유사하니 이해하는데는 어려움이 없을 겁니다. 세션 관련 함수를 제외한 나머지 세 가지의 함수는 서버&클라이언트 세션 기능을 구현하기 위한 보조함수들로 필히 사용되어야 합니다. 각 함수별로 기능을 간단히 살펴보면,
tagext_head() 함수는 "<HEAD> ...... </HEAD>" 태그를 작성해 주는 함수로 이 함수 내에서 자바스크립트와 PHP 스크립트를 연결하는데 필요한 자바스크립트 함수 및 변수 처리 부분이 작성되어 있습니다.
tagext_body() 함수는 "<BODY> ...... </BODY>" 태그를 작성해 주는 함수로 이 함수 내에서 자바스크립트와 PHP 스크립트를 연결하는데 필요한 <FORM> 태그 및 <INPUT> 태그가 작성되어 있습니다.
submit_anchor() 함수는 <A> 태그를 대신하는 함수로 submit하기 전에 tagext_body()에서 작성된 <INPUT> 태그의 값을 설정하고 serialize하기 위한 자바스크립트 함수 goHref()를 호출하는 역할을 합니다. 자바스크립트 함수 goHref() 함수는 tagext_head() 함수 내에 작성되어 있습니다.
예제 파일 구성
아래의 예제는 실제 홈페이지에 적용할 수 있는 완성된 프로그램이 아니고, 단지 클라이언트 세션이 어떻게 이루어지는지를 보여주기 위한 실험적인 프로그램이니 참고만 하세요.
- common.php : 모든 페이지에서 공용으로 쓰이는 변수와 함수가 정의된 인클루드 파일
- sess.php : 세션 시작 페이지
- page1.php : 페이지 #1
- page2.php : 페이지 #2
- page3.php : 페이지 #3
- page4.php : 페이지 #4
- sess_end.php : 세션 종료 페이지
다운로드
(수정:2010.1.12) 관련 파일을 이곳에서 다운로드 받으세요.

Posted by 방글24