블로그 이미지
물결(Wave)
하고 싶은 것만 하며 살고 싶다

calendar

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

이번 시간에는 주소록의 뼈대를 만들것이다.
간단한 DB 테이블을 하나 만들고, PHP를 이용해서 DB작업을 위한 서버프로그램을 만들것이다.
그리고 다음장에서 주소록의 핵심인 주소록의 데이터를 사용자가 입력/수정/삭제 할 수 있는 HTML페이지를 작성하도록 하겠다.

DB

주소록은 간단하게 만들기로 하였다.
이름,연락처,주소 그리고 인덱스.
총 4개의 필드만 필요하다. 뭐 더 만들고 싶은 필드가 있으면 그건 각자 알아서...

CREATE TABLE addressbook (
  idx INT NOT NULL AUTO_INCREMENT ,
  name VARCHAR( 30 ) NOT NULL ,
  tel VARCHAR( 30 ) NOT NULL ,
  addr VARCHAR( 100 ) ,
  PRIMARY KEY ( idx )
)



서버프로그램(PHP)

서버프로그램은 클래스를 사용하기로 한다.
혹, 클래스가 잘 적응이 안되는 분도 이기회에 클래스를 한번 써보는것도 나쁘지는 않으리라 생각한다.
클래스를 설계할때 고민해야 할 것은 역할의 분리이다. 하나의 메소드에게는 한가지 일만 시키는것이 좋다.

직원 A에게 복사를 하는 일과 서류를 작성하는일, 거래처를 관리하는 일을 모두 맡겨왔는데
갑작스레 A가 사표를 낸다면

  1. A가 해왔던 세 가지 일을 모두 할 줄 아는 직원을 뽑거나
  2. 각각의 일을 맡을 세명의 직원을 뽑아야 한다.

하지만 처음부터 각 업무를 서로 다른 사람이 해왔다면 필요한 일만 할줄 아는 사람을 새로 뽑으면 된다.

우리의 주소록은 비교적 간단하므로 클래스를 구성하는데 별 무리가 없을것이다.
주소록 클래스가 할일을 살펴보면

  1. 주소록에 새로운 데이터 추가
  2. 입력된 데이터의 수정/삭제
  3. 입력된 데이터 추출

이상이다.

그럼 클래스를 만들어보자.

* 주소록 클래스는 PHP4도 호환이 가능하도록 작성할 예정이므로 __constructor__ 같은 PHP5전용 코드는 사용하지 않을것이다.

[class_addressbook.php]

class AddressBook{
   var $conn;

   //생성자
   function AddressBook($conn=Null){
       if($conn == Null){
           return false;
       }

       $this->conn = $conn;
   }

   //데이터 입력
   function addAddress(){}

   //데이터 수정
   function updateAddress(){}

   //데이터 삭제
   function deleteAddress(){}

   //데이터 추출
   function getAddress(){}
}

AddressBook 클래스의 기본 골격은 위와 같다.
DB연동이 주된 업무이니 생성자에서는 DB 커넥터를 기본으로 지정한다.

이제 메소드를 하나하나 구현해보자

1.데이터 입력: addAddress()

입력해야 할 필드는 총 4개인데 그중 idx는 자동으로 생성되니 addAddress 메소드에는 3개의 값만 던져주면 되겠다. 바로 이름,연락처,주소이다. 그중 주소는 NOT NULL 이 아니니 이점에 유의하자

function addAddress($name,$tel,$addr=Null){
   if(empty($name) == true || empty($tel) == true){
       return false;
   }
   //주소값이 주어지지 않으면 db에 null 을 입력한다. 공백을 입력하게 되면 is null 같은 검색이 안된다.
   if($addr == Null){
       $addr = 'null';
   }else{
       $addr = "'".$addr."'";
   }

   $qry = "INSERT INTO addressbook SET\n"
           ."name='".$name."',"
           ."tel='".$tel."',"
           ."addr=".$addr;

   $res = mysql_query($qry,$this->conn);

   //입력이 성공하면 해당 row의 index 번호를 반환한다
   if($res != false){
       return mysql_insert_id();
   }else{
       return false;
   }
}


2.데이터 수정: updateAddress()

데이터의 수정은 데이터의 입력과 비슷하다. 단지 어떤 데이터를 수정하느냐를 결정하는 idx가 주어지는 것만 다를뿐이다.

function updateAddress($idx,$name,$tel,$addr=Null){
   if(empty($idx) == true || empty($name) == true || empty($tel) == true){
       return false;
   }

   if($addr == Null){
       $addr = 'null';
   }else{
       $addr = "'".$addr."'";
   }

   $qry = "UPDATE addressbook SET\n"
           ."name='".$name."',"
           ."tel='".$tel."',"
           ."addr=".$addr."\n"
           ."WHERE idx=".$idx;

   return mysql_query($qry,$this->conn);
}


3.데이터 삭제: deleteAddress()


데이터의 삭제는 더 간단하다. 삭제할 row의 idx값만 주면 된다.

function deleteAddress($idx=Null){
   if($idx == Null){
       return false;
   }

   $qry = "DELETE FROM addressbook WHERE idx=".$idx;

   return mysql_query($qry,$this->conn);
}



4.데이터 추출: getAddress() + getAllAddress()

데이터 추출은 좀 다르게 구현을 해야 한다. 하나의 레코드만 추출 할 경우와 전체 레코드를 추출할 경우를 구분해야 하기 때문이다. 위에서도 하나의 말했듯 메소드에게는 하나의 일만 시키는 것이 좋으므로 데이터 추출은 두개의 메소드로 구현하기로 하자 getAddress()와 getAllAddress() 가 바로 그것이다.

function getAddress($idx=Null){
   if($idx == Null){
       return false;
   }

   $qry = "SELECT * FROM addressbook WHERE idx=".$idx;
   $res = mysql_query($qry,$this->conn);

   if(mysql_num_rows($res) > 0){
       return mysql_result($res,0);
   }else{
       return Null;
   }
}
function getAllAddress(){
   $qry = "SELECT * FROM addressbook";
   $res = mysql_query($qry,$this->conn);

   if(mysql_num_rows($res) > 0){
       $result = array();
       while($row = mysql_fetch_assoc($res)){
           array_push($result,$row);
       }

       return $result;
   }else{
       return Null;
   }
}

이제 필요한 메소드가 다 만들어졌다.
그런데 데이터 입력과 수정작업을 처리하는 메소드에 중복되는 코드가 보인다.
바로 SQL 쿼리문을 작성하는 부분인데 이부분은 따로 쿼리 작성 메소드를 만들어서 빼는게 좋겠다.
이름하여 캡슐화...

function makeQuery($name,$tel,$addr=Null){
   if(empty($addr) == true){
       $addr = 'null';
   }else{
       $addr = "'".$addr."'";
   }

   $str = "name='".$name."',\n"
         ."tel='".$tel."',\n"
         ."addr=".$addr;

   return $str;
}

캡슐화를 했으니 addAddress()와 updateAddress()메소드를 수정해야한다.
전체를 수정하는건 아니고 SQL쿼리 작성 부분만 수정하면 된다.

addAddress()
   $qry = "INSERT INTO addressbook SET\n";
   $qry .= $this->makeQuery($name,$tel,$addr);

updateAddress()
   $qry = "UPDATE addressbook SET\n";
   $qry .= $this->makeQuery($name,$tel,$addr);
   $qry .= " WHERE idx=".$idx;

드디어 AddressBook 클래스가 완성됐다.
사실 제대로된 객체지향 프로그래밍을 하자면 AddressBook 클래스 외에 Address 클래스도 필요하다.
하지만 지금까지의 과정도 쉽고 단순하게 하자는 당초의 계획과는 달리 복잡해진감이 없지않으므로 Address클래스는 일단 생략하고 클라이언트 프로그램 완성 후에 리팩토링을 하겠다.


테스트

DB에 테이블도 만들었고 클래스도 만들었으니 테스트를 해보자.
웹프로그래밍에 TDD(Test Driven Develope)적용이 필요한지에 대해서는 의견이 분분하지만 개념을 알필요는 충분하다고 본다.

에디터에서 다음과 같은 코드를 작성한 후 브라우져로 결과를 확인해보자.
<?php
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);
assert_options(ASSERT_CALLBACK, 'assert_handler');
assert_options(ASSERT_BAIL,1);

function assert_handler($file,$line,$code){
   echo "Assertion Failed:<br />
       File '$file'<br />
       Line '$line'<br />
       Code '$code'<br />";
}

include_once 'db_conn.php'
include_once 'class_addressbook.php';

echo 'start test<br />';

assert('$BOOK = new AddressBook($conn)');
echo 'class construction test ... [OK]<br />';

assert('$BOOK->addAddress("이효리","011-1111-1111")');
assert('$BOOK->addAddress("강동원","011-2222-2222","우리집")');
assert('$BOOK->addAddress("Jackson","060-3333-3333","America")');
echo 'address data INSERT test ... [OK]<br />';

assert('$BOOK->updateAddress(1,"이효리","016-4444-4444","우리집")');
assert('$BOOK->updateAddress(2,"강동웜","011-2222-2222","북한")');
echo 'address data UPDATE test ... [OK]<br />';

assert('$BOOK->getAddress(3)');
echo 'an address data GET test ... [OK]<br />';

assert('$BOOK->deleteAddress(3)');
echo 'an address data DELETE test ... [OK]<br />';

assert('$BOOK->getAllAddress()');
echo 'all address data GET test ... [OK]<br />';

echo 'All Test Success!!';

$qry = "DELETE FROM addressbook";
mysql_query($qry,$conn);

$qry = "ALTER TABLE addressbook auto_increment=1";
mysql_query($qry,$conn);
?>

브라우져에 All Test Success!! 가 출력됐다면 성공이다.

테스트가 성공했으면 실제 쓸 소스를 작성해야 한다.
이미 테스트 코드에서 다 만들었으니 그냥 가져다 쓰면 된다.

[execute_address.php]

//include =================================================
include_once 'db_conn.php';
include_once 'class_addressbook.php';


//request vars ============================================
$name = isset($_POST['name'])?$_POST['name']:Null;
$tel     = isset($_POST['tel'])?$_POST['tel']:Null;
$addr  = isset($_POST['addr'])?$_POST['addr']:Null;
$idx    = isset($_POST['idx'])?$_POST['idx']:Null;
$job    = isset($_POST['job'])?$_POST['job']:Null;

$result = false;

if($job == Null || false !== $BOOK = new AddressBook($conn)){
   switch($job){
       case('add'):
           $result = $BOOK->addAddress($name,$tel,$addr);
       break;

       case('update'):
           $result = $BOOK->updateAddress($idx,$name,$tel,$addr);
       break;

       case('delete'):
           $result = $BOOK->deleteAddress($idx);
       break;

       case('get'):
           $result = $BOOK->getAddress($idx);
       break;

       case('get_all'):
           $result = $BOOK->getAllAddress();
       break;
   }
}


준비끝

아직 완성은 아니지만 서버쪽 코딩이 끝났다.
완성이 아니라고한 이유는 php 처리 결과를 javascript 로 보내는 코드가 빠졌기 때문이다.
이 부분은 클라이언트 코딩할때 추가하기로 한다. 한글 인코딩 문제도 있고 JSON과 XML등등 데이터 가공과정을 거쳐야 하기때문이다.

여기까지는 그리 힘들지 않을것이라 본다.
어려운 부분은 없었던것 같고, 다만 클래스나 assert() 함수가 낯선 분들이 있을지도 모르겠다.
다음 포스팅에서는 AJAX애플리케이션의 핵심인 클라이언트 코딩을 하겠다.
DOM을 많이 사용해야하니 DOM에 자신 없는 분은 미리 [DOM]에 대해 공부를 하시길...
다음 링크를 따라가면 DOM에 대해 배울수 있다.

DOM3 - http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/Overview.html#contents
DOM3 Event - http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html
HTML DOM - http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-39872903

신고
posted by 물결(Wave)