강의 컨설팅 트레이닝 무료진단 무료책자 마케팅편지 마케팅정보공유 다이어리 서비스제휴 고객센터

PHP 답변형 게시판 / 자료실 /PHP강좌
작성자 : 13 김영철
등록날짜 : 2009.01.13 14:49
6,168

1차 프로젝트의 연장선상에서 PHP+MySQL을 이용한 응용 프로그램을 만들어 보겠습니다.

우선 글 쓰기, 보기, 수정, 삭제, 목록 보기 등 게시판의 5대 기본 기능에서
한 발 더 나아가 파일 첨부, 검색 기능을 추가해보겠습니다.
음... 팁으로 아주 기본적인 관리자 기능(특정 글 선택 후 삭제 및 수정 기능)도 만들어 보죠.

이어서, 가능하다면 온라인 투표 프로그램도 만들어보고,
회원제 게시판(BBS)도 만들어보면 좋겠습니다.
그러자면 회원 가입 기능, 로그인 기능, 관리자용 회원 관리 기능 등 여타 기능들을 구현해야겠지요...
회원 인증 기능도 쿠키를 사용할 수도 있고 세션을 사용할 수도 있는데, 이것도 한번 짚었으면 좋겠습니다.

욕심은 많은데 일주일에 기껏해야 겨우 몇 시간 품을 들여 언제쯤이나 다~ 완성할 수 있을런지...

아래 [그림1]과 같이 파일을 선택하는 폼을 하나 만들어 보겠습니다.
[찾아보기...]를 클릭하면 [그림2]와 같이 파일 선택 대화상자가 나타나야 하는 겁니다.

[그림1]
[그림2]

이 기능은 의외로 간단합니다.
우선 아래와 같이 입력하면 [그림1]과 같은 파일 선택 폼이 만들어집니다.

파일 이름은 upload.html로 합시다.

  1. <html>
  2. <head>
  3.    <title>PHP 파일 업로드 기능</title>
  4.    <meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
  5. </head>
  6. <body>
  7. <form method="POST" ENCTYPE="multipart/form-data" action="upload_ok.php">
  8. <table width="500" border="0" align="center" bgcolor="dddddd">
  9.         <tr>
  10.                 <td width="600" colspan="2" align="center"><b>파일 업로드 기능</b></td>
  11.         </tr>
  12.         <tr>
  13.                 <td width="100" align="center">파일명</td>
  14.                 <td width="500"> <input type="file" name="upfile" size="20">(파일의 용량 제한 : 20M)</td>
  15.         </tr>
  16.         <tr>
  17.                 <td align="center" colspan="2">
  18.                         <input type="submit" value="전송"> <input type="reset" value="취소">
  19.                 </td>
  20.         </tr>
  21. </table>
  22. </form>
  23. </body>
  24. </html>



여기서 유의해야 할 것은 7행과 14행밖에 없습니다.

먼저 7행을 보면,
form 태그의 ENCTYPE 속성에 "multipart/form-data"를 써 줍니다. 이 줄이 바로 폼에 입력된 데이터를 파일 형태로 전송하는 역할을 합니다.
ENCTYPE은 서버에 보낼 데이터의 타입을 규정합니다. 기본값은 "application/x-www-form-urlencoded"입니다. 그러나 파일을 전송해야할 때는 반드시 "multipart/form-data"를 써야합니다.

너무 어렵게 생각하지 마시고, 그냥 파일을 업로드해야할 경우에는
form 태그 안에 ENCTYPE="multipart/form-data"를 쓰면 되는구나, 그렇게 생각하세요.

그리고 14행.
input 태그의 TYPE 속성에 "file"을 설정하면, 위 [그림1]과 같이 [찾아보기...] 버튼이 포함된 한줄 글 입력 상자가 표시됩니다.

그냥 이렇게만 하면 일단 PC의 파일을 선택할 수 있는 기능이 구현된 것입니다. 쉽죠? 전부 HTML 태그입니다. PHP 프로그램 요소는 하나도 없습니다.

이제는 선택된 파일을 서버로 전송하는 기능이 필요합니다.
다음 시간에 하죠....

upload.html에서 파일을 선택한 다음 [전송] 버튼을 눌렀을 때 서버로 파일을 전송하는 기능을 하는 프로그램입니다.
성공적으로 파일을 전송하면 다음과 같이 전송된 파일의 각종 정보가 보이도록 해보겠습니다.


자세한 설명은 다음 시간에 합니다~
우선 코드부터 주~~~~욱 훑어보세요...

  1. <?
  2. // 업로드한 파일이 저장될 디렉토리 정의
  3. $target_dir = "up";  // 서버에 up 이라는 디렉토리가 있어야 한다.

  4. if(strcmp($upfile,"none")) {   // 파일이 업로드되었을 경우

  5. // 업로드 금지 파일 식별 부분
  6.     $filename = explode(".", $upfile_name);
  7.     $extension = $filename[sizeof($filename)-1];
  8.         
  9.     if(!strcmp($extension,"html") ||
  10.        !strcmp($extension,"htm") ||
  11.        !strcmp($extension,"php") ||      
  12.        !strcmp($extension,"inc"))
  13.     {
  14.        echo("업로드 금지 파일입니다.");
  15.        exit;
  16.     }

  17. // 동일한 파일이 있는지 확인하는 부분
  18.     $target = $target_dir . "/" . $upfile_name;
  19.     if(file_exists($target)) {
  20.        echo("동일 파일명 존재");
  21.        exit;
  22.     }

  23. // 지정된 디렉토리에 파일 저장하는 부분
  24.     if(!copy($upfile,$target)) {   // false일 경우
  25.        echo("파일 저장 실패");
  26.        exit;
  27.     }

  28. // 임시 파일을 삭제하는 부분
  29.     if(!unlink($upfile)) { // false일 경우
  30.        echo("임시 파일 삭제 실패");
  31.        exit;
  32.     }
  33. ?>  

  34. <html>
  35. <body>
  36.     <table width="500" border="0" cellspacing="1" cellpadding="2" align="center">
  37.     <tr>
  38.        <td colspan="2" align="center" bgColor="#CCCCCC" width="100%"><font size=2><b>>>
  39.             업로드 성공 <<</b></font></td>  
  40.     </tr>
  41.     <tr>
  42.        <td align="left" bgColor="#EEEEEE" width="120"><font size=2>파일명</font></td>
  43.        <td bgColor="#EEEEEE"><font size=2><?echo("$upfile_name")?></font></td>
  44.     </tr>
  45.     <tr>
  46.        <td align="left" bgColor="#EEEEEE" width="120"><font size=2>임시 저장 파일명</font></td>
  47.        <td bgColor="#EEEEEE"><font size=2><?echo("$upfile")?></font></td>
  48.     </tr>
  49.     <tr>
  50.        <td align="left" bgColor="#EEEEEE" width="120"><font size=2>파일 크기(Bytes)</font></td>
  51.        <td bgColor="#EEEEEE"><font size=2><?echo("$upfile_size")?> Bytes</font></td>
  52.     </tr>
  53.     <tr>
  54.        <td align="left" bgColor="#EEEEEE" width="120"><font size=2>파일의 MIME Type</font></td>
  55.        <td bgColor="#EEEEEE"><font size=2><?echo("$upfile_type")?></font></td>
  56.     </tr>
  57.     </table>

  58. <?
  59. } else {
  60. ?>
  61.         <table width="500" border="0" cellspacing="1" cellpadding="2" align="center" bgcolor="#FFCCFF">
  62.     <tr>
  63.        <td width="100%" align="center" bgColor="#CCCCCC"><font size=2><b>업로드 실패!!!</b></font></td>
  64.     </tr>
  65.     </table>
  66. </body>
  67. </html>

  68. <?
  69. }
  70. ?>

바로 설명을 드리죠.
앞의 소스 코드와 비교해 가면서 보시는 게 좋습니다.

[소스코드 새창에서 열기]



  1. $target_dir = "up";

    파일이 업로드될 디렉토리 이름을 $target_dir 변수에 저장을 합니다.
    실제 서버에 up 이라는 디렉토리가 있어야 합니다. 만약에 리눅스 시스템이라면 모든 이용자가 디렉토리 내에 파일을 읽고 쓸 수 있도록 퍼미션을 777로 주어야 합니다.(어떻게 퍼미션 설정하는지는 본 강좌 주제와 다소 벗어나므로 생략합니다~~ )

  2. if(strcmp($upfile,"none")) {   // 파일이 업로드되었을 경우

    upload.html에서 파일을 선택해서 [전송] 버튼을 눌렀는데, 정상적으로 업로드되지 않았거나 파일을 선택하지 않고 [전송] 버튼을 눌렀을 경우에는 "none"이라는 문자열을 보내게 됩니다.
    위 조건문은 "none"이라는 문자열이 전송되어왔는지를 검사하는 문장입니다.

    strcmp 함수는 두 개의 문자열을 비교하는 함수입니다.
    위에서는 $upfile의 값과 "none"이라는 문자열을 비교합니다. 이렇게 두 개의 문자열을 비교해서 같으면(참이면) 0을, 아니면 0이 아닌 값을 반환하는 기능을 합니다.
    따라서 $upfile의 값이 "none"이면 strcmp($upfile,"none")의 값이 0이 되므로 5행의 if 조건문은 거짓이 됩니다. (if나 while과 같은 조건문에서 0은 거짓을 나타냅니다. 반대로 0이 아닌 수는 참을 가리킵니다.) 조금 헤깔릴 수 있는 부분입니다.

    if(strcmp($upfile,"none")) 문장은 이렇게 바꿀 수도 있습니다.
    if($upfile != "none")
    반대로, if(!strcmp($upfile,"none")) 은,
    → if($upfile == "none") 와 같은 의미가 됩니다.

  3.     $filename = explode(".", $upfile_name);
  4.     $extension = $filename[sizeof($filename)-1];

    8행과 9행에서는 파일 전체 이름(확장자까지 포함한 이름)을 순수 파일 이름과 확장자로 분리하게 됩니다.
    explode 함수는 특정 구분자를 기준으로 문자열을 나누어 배열에 저장하는 역할을 합니다.
    예를 들어, $day = explode("-","2002-12-25") 이라고 하면,
    $day[0] → "2002"
    $day[1] → "12"
    $day[2] → "25" 가 각각 저장됩니다.

    따라서 위 8행에서는, 점(.)을 기준으로 분리하는 것이기 때문에, 만약 파일 이름이 itmembers.jpg라고 한다면,
    $filename[0] → "itmembers"
    $filename[1] → "jpg" 가 각각 저장됩니다.

    8행에서 분리한 문자열 중 확장자만 따로 $extension 변수에 저장하는 것이 9행입니다.
    확장자는 맨 마지막 배열에 들어 있겠죠? 위의 예에서는 $filename[1]에 들어 있을 겁니다.
    9행을 보면 $filename 배열의 크기를 구하여 -1을 합니다. 위와 같은 경우라면 $filename의 크기는 2가 되겠죠.
    $filename[0]과 $filename[1], 이렇게 두 개니까요.
    이렇게 구한 2에서 1을 뺀 수를 배열 요소로 갖게 되면 결국 $filename[1] 이 되겠죠. 여기에 확장자를 저장하게 됩니다.
    이렇게 복잡하게 구하는 이유는, 리눅스에서와 같이 파일 이름에 점(.)이 여러개 포함된 경우도 있기 때문입니다.
    윈도우즈에서라면 대부분 두번째 배열에 확장자가 저장되어 있겠지만요...

    잠깐, 그런데 $upfile_name 이라는 변수는 도대체 어디에서 나왔을까요???
    앞 강좌에서 upload.html 파일의 폼 태그에서 INPUT name을 upfile로 지정한 건 기억나죠?
    그래서 upload_ok.php의 $upfile 변수는 바로 이걸 뜻합니다.
    그런데, INPUT type이 "file"인 경우에는 $upfile에 "_name"이 붙은 새로운 변수가 자동으로 생성됩니다. 즉 $upfile_name 이라는 변수가 자동으로 만들어진다는 것이죠. 여기에 업로드된 파일의 이름(확장자 포함)이 저장되는 것입니다.
    이 외에도 $upfile_size, $upfile_type 등의 변수가 자동으로 생성됩니다.
    $upfile_size에는 업로드한 파일의 크기(byte 단위)가 저장되고, $upfile_type에는 업로드된 파일의 형식(MIME 타입)이 자동으로 저장됩니다.

    49, 53, 57, 61행을 유심히 보면 각각의 변수가 어떤 역할을 하는지를 잘 알 수 있습니다.


  5.     if(!strcmp($extension,"html") ||
  6.        !strcmp($extension,"htm") ||
  7.        !strcmp($extension,"php") ||      
  8.        !strcmp($extension,"inc"))
  9.     {
  10.        echo("업로드 금지 파일입니다.");
  11.        exit;
  12.     }

    5행에서 strcmp 함수의 용도는 이미 알아 보았습니다.
    따라서, 11행은 $extension 즉, 파일 확장자가 "html" 이거나
    12행, "htm" 이거나
    13행, "php" 이거나
    15행, "inc" 이면
    17,18행을 실행하라는 뜻이겠죠.
    ||는 or를 뜻한다는 거 아시죠?

  13.     $target = $target_dir . "/" . $upfile_name;
  14.     if(file_exists($target)) {

    $target 변수에는 디렉토리 이름과 파일 이름을 결합한 full name이 들어가게 됩니다.
    3행에서 $target_dir을 "up"이라고 설정했으니, 만약 업로드한 파일 이름이 "itmembers.jpg"라면,
    $target에는 "up/itmembers.jpg" 가 저장됩니다.

    22행의 file_exists 함수는 동일한 파일명을 가진 파일이 있는지 비교하는 역할을 합니다.
    $target과 동일한 파일이 있으면 23행을 실행하게 됩니다.

  15.     if(!copy($upfile,$target)) {   // false일 경우

    copy 함수는 파일을 지정한 디렉토리에 복사하는 기능을 합니다.
    $upfile을 $target으로 복사하게 됩니다. 이때 $target은 디렉토리 이름과 파일 이름이 모두 결합된 full name이어야 합니다.
    28행의 조건문은, 이렇게 복사를 하는데 '만약 복사를 실패하게 되면'이라는 뜻이 되겠죠...

  16.     if(!unlink($upfile)) { // false일 경우

    unlink 함수는 특정 파일을 삭제하는 기능을 합니다.
    따라서 34행은 '$upfile 삭제에 실패했을 경우'라는 조건문이 되는 겁니다.




이 정도 설명을 드렸으니, 소스를 다시 한번 주~욱 보시면 이해가 되시겠죠?

여러 개의 파일을 동시에 첨부하여 업로드할 수 있는 기능입니다.



일단 소스부터 볼까요?

  1. <html>
  2. <head>
  3.    <title>복수 개의 파일 업로드 기능</title>
  4.    <meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
  5.    <style type="text/css">
  6.    BODY, TD, INPUT {font-family:굴림;font-size:9pt;color:#000000;}
  7.    </style>
  8. </head>
  9. <body>
  10. <form method="POST" ENCTYPE="multipart/form-data" action="multiupload_ok.php">
  11. <table width="500" border="0" align="center" bgcolor="dddddd">
  12.         <tr>
  13.                 <td width="600" colspan="2" align="center"><b>여러 개의 파일 업로드 기능</b></td>
  14.         </tr>

  15. <?
  16. // 업로드 파일 갯수 지정($num) : 여기서는 3개로 지정함
  17. for ($num = 1 ; $num <= 3 ; $num++) {
  18.         $selectfile = "inputname".$num; // input 태그의 name 속성 값을 inputname1, inputname2, inputname3으로 설정하기 위함
  19. ?>
  20.         <tr>
  21.                 <td width="100" align="center">파일명 <? echo "$num"; ?></td>
  22.                 <td width="500"> <input type="file" name="<? echo "$selectfile"; ?>" size="25">(파일의 용량 제한 : 20M)</td>
  23.         </tr>
  24. <?
  25. }
  26. ?>

  27.         <tr>
  28.                 <td align="center" colspan="2">
  29.                         <input type="submit" value="전송"> <input type="reset" value="취소">
  30.                 </td>
  31.         </tr>
  32. </table>
  33. </form>
  34. </body>
  35. </html>


여러 개의 파일을 선택한 다음 실제 서버에 파일을 기록하는 부분입니다.
좀 복잡합니다.
일단 소스부터 보고, 설명은 다음 시간에 하겠습니다.
코드 중간에 최대한 주석을 달아놓았으니 어느 정도 감~은 잡을 수 있을 겁니다.

아래 코드의 실행 결과 화면입니다.(파일을 세 개 첨부했을 경우입니다.)


  1. <html>
  2. <head>        
  3. <title>복수 개의 파일 업로드 결과 확인</title>
  4. <meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
  5. <style type="text/css">
  6.    BODY, TD, INPUT {font-family:굴림;font-size:9pt;color:#000000;}
  7. </style>
  8. </head>
  9. <body>

  10. <?
  11. $target_dir = "up";  // 업로드한 파일이 저장될 디렉토리. 서버에 up 이라는 디렉토리가 있어야 한다.
  12. $uploaded_yn = "N"; // 기본값으로 N 설정. 파일이 하나라도 업로드될 경우 나중에 "Y"로 바꾸게 됨.

  13. for ($num = 1 ; $num <= 3 ; $num++) { // 업로드한 파일이 최대 3개일 경우
  14.         $upfile = ${"inputname".$num} ; // ${selectfile1} → $selectfile1 과 동일. 임시 파일명
  15.         $upfile_name = ${"inputname".$num."_name"} ; // INPUT 태그의 이름 뒤에 "_name"을 붙이면 실제 파일 이름의 변수가 된다. PHP에서 자동 생성되는 변수명.
  16.         $upfile_size = ${"inputname".$num."_size"} ; // 파일 사이즈
  17.         $upfile_type = ${"inputname".$num."_type"} ; // 파일 타입
  18.         if(!strcmp($upfile,"none")) {   // $upfile이 "none"이면 0, 아니면 1이 됨. 따라서 업로드되지 않았을 경우에 strcmp 결과는 0이 되고, !strcmp 이므로 if 조건문은 1이 되어 참이 됨. 으~ 복잡해라. 한마디로 파일이 업로드되지 않았을 경우 아래 코드를 실행하라는 뜻.
  19.                 continue; // 아래 코드를 실행하지 말고 for 문으로 다시 돌아가라는 뜻.
  20.         } else { // 파일이 업로드되었다면...
  21.             $target = $target_dir . "/" . $upfile_name;
  22.             if(!copy($upfile,$target)) {   // false일 경우
  23.                continue;
  24.                 }
  25.                 $uploaded_yn = "Y";
  26. ?>

  27.     <table width="500" border="0" cellspacing="1" cellpadding="2" align="center">
  28.     <tr>
  29.        <td colspan="2" align="center" bgColor="#CCCCCC" width="100%"><font size=2><b>>> 업로드 성공 <<</b></font></td>
  30.     </tr>
  31.     <tr>
  32.        <td align="left" bgColor="#EEEEEE" width="120"><font size=2>파일명</font></td>
  33.        <td bgColor="#EEEEEE"><font size=2><?echo("$upfile_name")?></font></td>
  34.     </tr>
  35.     <tr>
  36.        <td align="left" bgColor="#EEEEEE" width="120"><font size=2>임시 저장 파일명</font></td>
  37.        <td bgColor="#EEEEEE"><font size=2><?echo("$upfile")?></font></td>
  38.     </tr>
  39.     <tr>
  40.        <td align="left" bgColor="#EEEEEE" width="120"><font size=2>파일 크기(Bytes)</font></td>
  41.        <td bgColor="#EEEEEE"><font size=2><?echo("$upfile_size")?> Bytes</font></td>
  42.     </tr>
  43.     <tr>
  44.        <td align="left" bgColor="#EEEEEE" width="120"><font size=2>파일의 MIME Type</font></td>
  45.        <td bgColor="#EEEEEE"><font size=2><?echo("$upfile_type")?></font></td>
  46.     </tr>
  47.     </table>

  48. <?
  49. } // 22행의 else 닫기

  50. if ($uploaded_yn == "N") {
  51. ?>
  52.         <table width="500" border="0" cellspacing="1" cellpadding="2" align="center" bgcolor="#FFCCFF">
  53.     <tr>
  54.        <td width="100%" align="center" bgColor="#CCCCCC"><font size=2><b>업로드 실패!!!</b></font></td>
  55.     </tr>
  56.     </table>
  57. </body>
  58. </html>

  59. <?
  60. } // 55행의 if 문 닫기
  61. } // 15행의 for 문 닫기
  62. ?>


정말 오랜만에 휴일을 즐기고 있습니다.
근 두 달만에 강좌를 업로드하네요.

오늘은 게시판에 검색 기능을 추가해보겠습니다.

검색 기능은 의외로 간단하게 구현됩니다.
원리는 매우 단순합니다.
사용자로부터 필드(컬럼) 이름과 검색어를 입력받으면, 이 필드(컬럼) 이름과 검색어로 된 조건절(where문) SQL 문장에 추가하면 됩니다.

예를 들면 이런 겁니다.

게시물 중에서 '제목'(subject)에 '테스트'라는 문자열이 있는 게시물을 찾고 싶다면,

SELECT * FROM tablename WHERE subject like '%테스트%'

이와 같이 하면 됩니다.

여기서 like는 와일드 카드를 사용할 수 있도록 합니다. %테스트%는  '테스트'가 포함된 모든 문자열을 말하는 겁니다.
테스트%는 '테스트'로 시작하는 문자열을, %테스트는 '테스트'로 끝나는 모든 문자열을 말합니다.
보다 자세한 내용은 본 사이트의 재미로 배우는 데이터베이스 입문 오라클 데이터 검색 Keywords(2) 강좌를 참조하세요.

자, 그럼 본격적으로 list.php 파일을 수정해 보겠습니다.

list.php는 PHP 게시판 프로젝트(1차)에서 만들었었죠?
PHP 게시판 프로젝트(1차) 강좌 제20강과 24강을 참조하세요.(20강의 소스 코드 73행을 조금 수정해야하는데, 그 설명을 24강에서 했습니다.)
수정된 list.php 파일은 자료실에 PHP 게시판 프로젝트 1차 완성본이라는 제목으로 등록되어 있습니다.

그럼, 위와 같이 수정된 list.php 파일이 있다고 가정하고...
이 파일에 약간의 코드만 추가하고 수정하면 검색 기능이 완성됩니다.

아래에 설명하고 있는 소스는 자료실에 HP 게시판 프로젝트 2 검색 기능(list.php 수정)라는 제목으로 등록해두었습니다.

  1. 먼저, 소스 파일 158~178행을 보세요.



    위의 코드는 목록 보기 페이지에 아래와 같은 검색 창을 보이게 합니다.


    코드를 설명드릴 게 있나....
    163행은 hidden 속성으로 페이지 번호를 넘깁니다.(사용자로부터 특정 값을 입력받는 게 아니라 현재 프로그램 내에서 설정된 $page 값을 넘기는 겁니다.)
    167행에서 '제목'을 기본값으로 선택(selected)해 놓았습니다.

  2. 13~16행은 위에서 입력받은 값으로 SQL 조건문(where절)을 구성하는 것입니다.


    $src_value 값이 있으면, 즉 검색어를 넘겨받았으면 $where 변수를 15행처럼 만드는 것입니다.

  3. 19행과 29행의 SQL 문에 $where를 추가하였습니다.(잘 살펴보세요~)


    특히 29행의 $where 위치에 주의하세요. $where의 위치에 따라 검색에 오류가 날 수 있습니다.
    order by 문은 where 문 뒤에 위치해야 합니다.

  4. 링크된 모든 곳에 src_name=$src_name&src_value=$src_value를 추가합니다.
    78, 116, 117, 123, 132, 139, 145, 146, 154행에서 적용되었습니다.

  5. 끝으로 list.php 외에
    글 쓰기, 수정, 삭제 관련 코드에서 링크 부분에도 src_name=$src_name&src_value=$src_value를 추가하면 끝납니다.


이미 지난 시간에 수차례에 걸쳐 파일을 업로드 기능에 대해 실습해 본 적이 있습니다.
이번 시간부터는 파일 업로드 기능을 실제 게시판에 적용해 보겠습니다.

앞서 파일 업로드 기능에 대해 어느 정도 이해를 하셨다면 그리 어려운 내용은 아닐 것입니다.
기존(PHP 게시판 1차 프로젝트)에 만든 다음과 같은 파일에 파일 업로드를 위한 코드를 추가해 주면 됩니다.



위의 파일 뿐만 아니라 bbs 테이블에 첨부 파일의 이름을 저장할 수 있는 필드를 추가해야 합니다.
PhpMyAdmin을 실행하여 아래와 같이 file_name1 과 s_file_name1 두 개의 필드를 추가합니다.



(※ phpMyAdmin 실행할 줄 아시죠? 오래 되어서 잊어버렸나요?
http://localhost/myadmin/ 라고 입력하면 됩니다.)

file_name1 필드에는 첨부 파일의 디렉토리와 파일 이름이 모두 저장되고, s_file_name1 필드에는 첨부 파일의 파일 이름만 저장합니다.

먼저 글 쓰기 폼에 파일을 첨부할 수 있는 폼을 추가하기 위해,
write.php 파일에 일부 코드를 추가합니다.

※ write.php 파일을 포함해 앞으로 설명하게 될 insert.php modify.php modify_ok.php view.php 파일은 모두 자료실에 등록되어 있습니다. 다운로드하셔서 참조하시기 바랍니다.

먼저 55행, form 태그에 ENCTYPE='multipart/form-data' 속성을 추가합니다.



이게 뭐냐구요? 혹시 기억이 안 나면 http://www.itmembers.net/board/view.php?id=php2&no=2” target=”_blank”>파일 업로드 기능 구현(1) upload.html 강좌를 다시 보세요~

그리고 아래와 같이 120~124행의 코드를 추가하면 됩니다.



자, 다 됐습니다.
write.php 파일을 실행해 볼까요?
아래와 같이 나오면 정상입니다.



추가 설명 필요없죠?

지난 시간에 파일을 첨부할 수 있는 폼을 만들었습니다.
이번 시간에는 첨부한 파일을 서버에 업로드하고 해당 정보를 실제 DB에 기록하는 부분을 분석해 봅니다. 파일 첨부 기능의 핵심이라고 할 수 있습니다.
(물론 이 모든 것은 이미 앞서 파일 업로드 기능 구현(1)~(3)을 통해 살펴 보았던 내용입니다.)

1차 프로젝트에서 만든 insert.php 파일에 아래와 같은 내용을 추가하거나 수정합니다.

  • 자료실에 1차 프로젝트 파일과 지금 이 강좌에서 설명하고 있는 내용으로 수정된 파일이 모두 등록되어 있습니다. 참조하세요…



19행부터 57행까지의 코드입니다.



달리 설명이 필요한 부분이 없습니다.
(이해가 안되는 부분은 파일 업로드 기능 구현 (1)~(3)의 강좌를 다시 한번 보시기 바랍니다.)
$msg에는 나중에 alert 창으로 표시될 문자열을 저장하고 있습니다.



63행을 보면,
기존의 sql 문에 '$target'과 '$upfile_name'를 추가하였습니다.
$target은 40행에서 지정한 변수이지만,
$upfile_name은 기존의 $upfile 변수에 PHP가 자동으로 생성한 변수입니다.(자세한 설명은 파일 업로드 기능 구현 (3) 강좌를 참조하세요.)
$target은 file_name1 필드에, $upfile_name은 s_file_name1 필드에 각각 저장됩니다.

68행에서 90행까지는 파일 업로드가 성공한 경우와 그렇지 않은 경우를 자바 스크립트를 이용하여 처리하고 있습니다.
파일 업로드가 성공하면 리스트 페이지로 이동하고, 오류가 발생하면 바로 전 페이지로 되돌아 가도록 되어 있습니다.



지난 시간 2회에 걸쳐 게시판의 글 쓰기 프로그램(write.php insert.php)에 파일 업로드 기능을 추가해 보았습니다.

이번 시간에는 마지막으로 글 수정(modify.php modify_ok.php) 및 내용 보기(view.php) 부분에서 관련 기능을 구현하기 위해 짚고 넘어가야 할 몇 가지만 얘기하겠습니다.

  1. modify.php 파일을 열어 80행과 148~157행을 아래와 같이 수정합니다.






wirte.php와 동일한데, 다만 152행에서와 같이 기존에 첨부한 파일의 이름을 보여주는 부분만 눈여겨 보시면 됩니다.(bbs 테이블의 s_file_name1 필드의 내용(첨부 파일 이름)을 보여주고 있습니다.)
웹 브라우저에는 아래와 같이 보입니다.



  1. modify_ok.php 파일은 지난 시간에 다루었던 insert.php 파일과 거의 비슷합니다.
    단, 69~71행에서와 같이 첨부 파일을 새로 업로드했을 경우에만 첨부 파일 이름이 기록된 fiel_name1 s_file_name1 필드의 내용을 업데이트해야 합니다. 그렇지 않고 다른 컬럼과 마찬가지로 그냥 업데이트하면 기존의 값을 지워버리게 됩니다.





  1. view.php 파일은 아래와 같이 두 부분을 수정합니다.





filesize는 파일의 크기를 byte로 구해주는 PHP 내장 함수입니다.
따라서 filesize($array[file_name1])은 file_name1에 저장된 값(디렉토리명 + 파일이름)에 해당되는 파일을 찾아 그 크기를 구해주는 기능을 합니다.
파일 크기를 바이트로 구한 다음, 1024로 나누면 KB가 됩니다.
그 값을 다시 소수점 반올림한 값으로 구하기 위해 round 함수를 사용했습니다.
Round(xxx,2)라고하면 xxx 값을 반올림하여 소수점 이하 둘째자리까지 구하게 됩니다.

85~100행은 파일 이름과 크기를 보여주고, 해당 파일로 링크를 걸어주는 코드입니다.



끝났습니다.

이제 list.php를 실행하면 아래와 같이 파일의 이름과 크기가 표시됩니다.


정말 오랜만에 강좌 업데이트합니다.
이번 주에 답변형 게시판에 대한 강좌를 시작하려고 하는데, 그보다 앞서 우선 여러 개의 파일을 첨부할 수 있는 기능을 추가해보겠습니다. 앞 강좌에서 1개의 파일을 첨부할 수 있는 기능을 추가했는데, 앞 강좌의 연장선상에서 진행하겠습니다. 사실 게시판을 만드는데 달랑 첨부 파일이 하나만 업로드할 수 있다면 기능이 좀 약하다는 느낌이 들잖아요.


이번 실습에서는 3개의 파일을 업로드할 수 있도록 하겠습니다. 여기에 약~~~간만 손되면 첨부 파일의 갯수는 맘껏 조정할 수 있습니다.

만들어 볼 폼음 우선 아래와 같습니다.


이 기능을 모두 구현하기 위해서는 다음과 같이 5개의 파일을 손 봐야 합니다.

  • 글 쓰기 폼과 DB 저장 부분 : write.php insert.php
  • 글 내용 보기 : view.php
  • 글 내용 수정 폼과 DB 저장 부분 : modify.php modify_ok.php



그 전에 DB 테이블에 첨부 파일의 이름을 저장할 수 있도록 몇 개의 필드를 추가해야겠죠.

이 강좌와 관련된 소스 파일(5개)은 자료실에 등록해 두었습니다. 참조하시기 바랍니다.

bbs 테이블 수정

기존 테이블은 첨부 파일을 하나만 저장할 수 있도록 되어 있었습니다.
첨부 파일 하나를 저장하기 위해서는 파일의 정확한 경로와 이름을 모두 저장하는 필드와 파일 이름만 저장하는 필드, 이렇게 두 개의 필드가 필요했습니다.
따라서 3개의 파일을 저장하기 위해서는 파일의 경로와 이름을 저장하는 필드, 파일 이름만 저장하는 필드 등 각각 2개씩 추가해야겠지요.



필드를 어떻게 추가해야하는지 모른다구요?
http://localhost/myadmin/ 이렇게 해서 추가를 합니다. 그래도 모르시겠다면 PHP 게시판 1 강좌 중에서 테이블 생성하는 부분을 참조하시기 바랍니다.


write.php

비교적 간단합니다.
기존 파일 첨부 부분을 아래와 같이 수정합니다.
for 문을 사용하여 파일 첨부 입력 폼을 3개까지 만들 수 있도록 했습니다.
여기서 주의할 것은 파일 첨부를 위한 input name의 속성 값이 각각 다르게 지정해야 한다는 겁니다.
127행을 보시면 name 속성에 $selectfile 값이 대입되도록 되어 있습니다.
$selectfile 값은 124행에서 지정하였듯이 "upfile"이라는 문자 뒤에 $num 값이 연결된 형식, 즉 upfile1 upfile2 upfile3 과 같은 식으로 지정되는 겁니다.



insert.php

이 강좌의 핵심이 되는 부분입니다.
그러나 기본적인 원리에 대해서는 이미 수 차례에 걸쳐 이미 설명을 드렸던 것이니 자세한 설명은 따로 하지 않겠습니다.
파일 업로드 기능 구현 및 게시판에 파일 첨부 기능 추가와 관련된 강좌를 참조하시기 바랍니다.

역시 for 문을 사용해서 업로드한 파일을 3개까지 반복하여 저장하고 있습니다.



25행을 보면, $upfile = ${"upfile".$num} 이라고 되어 있습니다.
$num의 값이 1,2,3으로 바뀔 때마다 $upfile의 값도 $upfile1, $upfile2, $upfile3으로 바뀌도록 한 것입니다.
변수를 지정할 때 중괄호 { } 의 용도에 대해 단적으로 알 수 있는 부분입니다.
중괄호 { }를 적절히 사용하면 변수 이름을 다양하게 응용할 수 있습니다.

만약 위 예에서 만약 $upfile = $upfle.$num 과 같이 했다면 어떻게 될까요?
그러면 $upfile에 저장된 값과 $num의 값이 합쳐져서 이상한 값이 $upfile에 저장될 것입니다.

마지막으로 insert 문을 볼까요?



이렇게 써도 되는데, 다음과 같이 필드명을 나열하여 쓰는 것이 정석입니다.
가끔 위와 같이 해서 저장이 안된다는 분들이 있어 아래와 같이 사용하기를 권장합니다.
(이 강좌를 처음부터 순서대로 제대로 따라하시면 상관없는데 그렇지 않은 경우에 저장이 안될 수 있으니까요...)

$sql = "insert into bbs
(number,name,password,email,homepage,subject,memo,count,ip,writetime,file_name1,s_file_name1,file_name2,s_file_name2,file_name3,s_file_name3)
values('','$name','$password','$email','$homepage','$subject','$memo',$count,'$ip',$writetime,'$target1','$upfile1_name','$target2','$upfile2_name','$target3','$upfile3_name')";



지난 시간에 write.php와 insert.php를 설명드렸는데요, 지난 시간 내용만 이해하셨다면 이번 시간에는 가볍게 넘어갈 수 있습니다.


이 강좌에서 설명하고 있는 소스 파일은 자료실에 등록되어 있습니다. 참조하시기 바랍니다.

view.php

24~27행까지는 첨부 파일의 크기를 구하는 부분입니다.




87~126행까지는 첨부 파일의 이름과 경로를 구하는 부분입니다. 기존 1개에서 3개로 늘린 것 뿐이니 별다른 설명이 필요 없을 것 같네요.



modify.php

전 시간에 설명드린 write.php와 비슷합니다. 글 수정 폼입니다.
배열의 첨자에 사용되는 변수의 값이 $num 의 값에 따라 변하는 것이 특징입니다.
잘 보시고 이해하세요.



modify_ok.php

27~72행을 보면 전 시간의 insert.php와 거의 같죠?
따로 설명드릴 게 없네요.



79~87행은 첨부 파일이 있을 경우에만 update 문을 이용해 DB를 수정하는 부분입니다. 기존 1개에서 3개로 늘린 것 뿐입니다.





게시판을 통해 메일을 통해 답변형 게시판의 원리와 구현 방법에 대한 설명을 부탁하신 분들이 꽤 있습니다. 저 역시 답변형 게시판의 구현을 2차 PHP 게시판 프로젝트의 주요한 목표로 설정해 놓고도 시간이 없어 진행하지 못했는데요, 이번 연휴를 맞아 드디어 시작하게 되었습니다.
짝~짝~짝~~~~~~ (자축의 박수부터 치고…)



대개의 프로그래밍이 그러하듯이 원하는 기능을 구현하기 위한 방법은 다양합니다.
답변형 게시판도 예외는 아닙니다. 답변 기능을 구현하는 로직은 여러 가지가 있습니다. 나름대로의 장단점이 있구요.
두 시간에 걸쳐 답변 기능을 구현하는 두 가지 원리를 소개해 드리는데, 이번 시간에 그 중 하나를 설명하겠습니다.
원리를 설명하고 난 다음에 구체적인 실습을 하겠습니다.

답변 기능을 구현하기 위해 가장 먼저 어떤 게 필요할까요?
답변 글과 원 글과의 관계에 대한 규정이 필요합니다. 다시 말해, '이 글은 어느 글(= 원 글)의 답변 글이다'라는 걸 답변 글 어딘가에 기록해 둬야 한다는 겁니다.
그리고 또 하나, 이 글은 몇 단계(깊이)의 답변 글이냐 하는 것도 중요합니다. 원 글의 답변이 1단계라면, 그 답변의 답변은 2단계라고 할 수 있고, 이렇게 계속해서 '답변의 답변의 답변의 답변의 답변…'과 같은 식으로 확대될 수 있는 겁니다.
마지막으로 글 정렬 순서인데요, 이렇게 복잡하게 얽힌 글 목록을 원 글과 답변 글의 관계를 고려하여 보기 좋게 나열해야 하는 겁니다.

기본적인 원리는 위와 같지만 실제 구현하기 위한 방법에는 약간의 차이가 있습니다.
그 중 하나를 지금부터 설명드리죠.

새로 글을 작성할 때 그 글을 구분하는 유일한 식별자가 무엇이죠?
지금까지 우리는 number 라는 필드에 고유한 값을 자동으로 입력되도록 했습니다. 가장 기본이 되는 식별자입니다.
거기에 답변 기능을 구현하기 위해 3개의 필드를 추가합니다.
list_numberdepth, parent 등 세 개의 필드가 필요합니다.(항상 이런 건 아니구요, 다음 시간에 사용할 방법은 두 개의 필드만 필요합니다.)


이제 글을 하나씩 등록해 볼까요?

  1. 첫 번째 글을 등록할 경우



    모든 번호가 다 1입니다.
    이것만 봐서는 도저히 알 수가 없습니다.

  2. 두 번째 글을 등록할 경우



    number는 순서대로 늘어나기 때문에 2가 됩니다.
    list_number는 화면에서 보여주는 순서이기 때문에 나중에 등록된 글을 먼저 보여주기 위해 두 번째 등록한 글이 1이 되고, 첫 번째 글은 2가 됩니다.
    답변 글이 아니기 때문에 depth는 1이 됩니다.
    마찬가지로 답변 글이 아니기 때문에 parent는 원 글의 number와 동일한 2가 됩니다.

    이 정도만으로도 아하~ 하고 깨닫는 분이 분명 있을 겁니다.

  3. 두 번째 글에 답변 글을 작성할 경우



    number는 순서대로 늘어나기 때문에 3이 됩니다.
    list_number는 화면에서 보여주는 순서라고 했죠? 가장 위쪽에 두 번째 글을 보여주고, 그 아래에 두 번째 글의 답변 글, 가장 아래에 첫 번째 글이 보이겠죠?
    정리하면, 두 번째 글의 답변 글은, 두 번째 글의 list_number보다 큰 첫 번째 글의 list_number값을 1 증가시키고(=3), 자신은 원 글의 list_number에 1을 더합니다(=2). 원 글(두 번째 글)의 list_number값은 그대로 둡니다(=1).
    depth는 답변 글이기 때문에 2가 되고,
    parent에는 원 글의 번호(number)인 2가 저장됩니다.

  4. 세 번째 글을 등록할 경우



    number는 순서대로 늘어나기 때문에 4가 됩니다. 고유 번호이죠.
    list_number는 화면에서 보여주는 순서라고 했죠? 지금 쓴 글이 가장 위쪽에 배치되어야 하므로, 자신의 글은 1이 되고, 나머지 글의 list_number의 값은 모두 1씩 증가시킵니다.
    depth는 답변 글이 아니므로 1이 되고,
    parent에는 원 글의 번호, 즉 자신의 번호(number)인 4가 저장됩니다.

    마지막으로 하나의 예만 더 들어 볼까요?

  5. 첫 번째 글의 답변 글을 작성할 경우



    number는 순서대로 5.
    list_number는 첫 번째 글의 list_number(=4)보다 큰 list_number가 없으므로 나머지는 모두 그대로 두고, 자신만 첫 번째 글의 list_number에 1을 더하게 됩니다(=5).
    depth는 답변 글이므로 2가 되고, (만약 답변의 답변일 경우에는 depth가 3이 되겠죠.)
    parent에는 원 글의 번호 (number)인 1이 저장됩니다.

    자~ 다 되었습니다.
    이제 list_number를 기준으로 다시 정렬해 볼까요?



    이해가 되시나요?


그런데, 이렇게 게시판을 구현하려고 하면,
게시판을 처음 만들 때부터 이를 고려해서, 글이 저장될 때마다 자신 뿐만 아니라 다른 게시물의 list_number의 값도 수정해야 합니다. 게시물의 수가 엄청나게 많다면 이것도 보통 일은 아니겠죠? 또한 이곳 게시판 강좌를 꾸준히 따라하셔서 나름대로 게시판을 만들어 운영하고 있는 분이라면 매우 난감한 일이 아닐 수 없습니다.

답변 기능까지 구현된 게시판을 처음부터 새로 설계한다면 고려해 볼만한 방식입니다만, 저를 믿고 이 프로젝트를 순서대로 따라하신 분이라면 다음 시간에 설명드릴 방법으로 한번 해보시는 게 어떨까 생각합니다. (물론 각각의 장단점은 모두 있어 어느 것이 월등히 좋다고 말씀드릴 수는 없겠네요…)



참고로 댓글은 답변형 게시판과는 또 다른 것입니다.
일반적으로 댓글이라고 하면 어떤 글에 대해 짤막하게 답변을 다는 것을 말하는데, 원본 글이 상단에 보이면서 하단에 여러 개의 댓글이 함께 보이는 것을 말합니다.
답변 글이 또 한번의 클릭을 해야 볼 수 있는데 반해, 댓글은 원 글의 내용을 보면서 바로 확인할 수 있다는 점에서 훨씬 편리한 커뮤니케이션 방법이라고 할 수 있습니다.



아래 그림은 제가 만든 DJ보드에서 댓글 두 개를 달았을 때의 모습입니다.



보시다시피, 원래의 글 밑에 두 개의 댓글이 바로 보이며, 또 댓글을 바로 달 수 있는 입력 폼이 함께 있습니다.

원리는 비교적 간단합니다. 답변형 게시판을 구현하는 것에 비하면 간단하다고 할 수 있죠.
그러나 답변형 게시판은 기존 테이블에 필드 두 세 개를 추가해서 만들 수 있는 반면, 댓글 게시판은 댓글을 저장하기 위한 별도의 테이블을 생성시켜야 합니다(꼭 이렇게 해야한다는 것은 아니지만...).

예를 들어, 자유게시판용 free 테이블이 있다면,

  1. 이 테이블의 댓글을 저장하기 위한 free_comment 테이블을 따로 만들어 둡니다.

  2. free_comment 테이블은 대개 다음과 같은 필드로 구성하면 됩니다.

    • 댓글 고유 번호(식별자) - 예) number
    • 원 글의 번호를 저장하기 위한 필드 - 예) parent
    • 댓글 작성자 이름, 아이디, 패스워드 등 - 예) name, userid, password
    • 실제 댓글이 저장되는 부분 - 예) comment
    • 댓글 작성자 IP 및 작성 시간 등 - 예) ip, wirtetime

    이제 어느 정도 감~이 잡히셨나요?
    이제 어떻게 해야할까요?

  3. 글 내용을 보는 화면(view.php) 하단에 댓글을 달 수 있는 입력 폼을 추가해야 하겠죠.

  4. 그리고 그 입력 폼에서 전달된 값을 저장할 수 있는 프로그램(예 comment_ok.php)을 만들어야겠지요.

  5. 글 내용을 보는 화면(view.php)에서는, 기본 글 내용 뿐만 아니라 연관된 댓글도 함께 보여줄 수 있는 로직을 구현해야겠지요.
    예를 들어, free 게시판의 3번 글의 내용을 보여 준다면, free_comment 테이블에서 parnet 값이 3 인 내용도 모두 읽어와 함께 보여 주면 됩니다.

  6. 마지막으로 자신이 작성한 댓글을 삭제할 수 있는 기능을 추가하면... 끝~~~~


어떻습니까?
원리가 어느 정도 이해되시나요?



보다 자세한 구현 방법은 답변형 게시판 강좌가 끝난 다음에 하겠습니다.

오늘 내용은 결코 쉽지가 않습니다.

처음부터 차례차례 정말 주의 깊게 보지 않으면 잘 이해가 안 되실 겁니다.
차근차근 보세요. 앞의 내용이 이해안되면 뒤로 갈수록 더 이해가 안됩니다.

지난 번에 설명드린 답변형 게시판 TYPE1에서는 기존 게시판 테이블을 기준으로 세 개의 필드(list_number, depth, parent)가 더 필요했습니다.
게다가 list_number 필드는 실제 글이 작성되거나 삭제될 때마다 기존의 list_number를 모두 바꿔줘야 합니다. (이해가 안 되시면 TYPE1 강좌를 다시 보시기 바랍니다.)

오늘 설명드리는 TYPE2는 두 개의 필드만 더 있으면 됩니다.
그리고 정렬된 목록을 보여주기 위한 글 번호인 list_number가 필요 없습니다.

원 글의 번호를 저장하는 replyno 필드와 답변 글의 깊이와 순서를 동시에 나타내기 위한 replyst 필드가 필요합니다. 물론 number 필드에는 자동으로 고유한 번호가 매겨지게 되어 있구요.

답변 글을 등록하고 목록을 정렬하는 순서는 다음과 같습니다.
이해가 안 되시면 그냥 넘어가도 됩니다.
단, 이해는 안 되어도 반드시 기억은 하고 있어야 합니다.
그래야 아래 규칙에 맞게 코딩을 할테니까요.



1. 원 글을 쓸 경우…. 즉 답변 글이 아닐 경우

  • ① number는 자동 증가합니다. (이건 당연한 거구요)
    ② replyno에는 number와 같은 값이 저장됩니다.
    ③ replyst에는 ‘AAAAA’가 저장됩니다.


2. 답변 글을 쓸 경우

  • ① number는 자동 증가합니다.
    ② 원 글의 replyst의 값을 구합니다.
    ③ 원 글의 깊이를 구합니다. 여기서 깊이라는 것은 처음 나오는 ‘A’의 위치입니다. 위치는 0부터 시작합니다. 따라서 ‘AAAAA’의 깊이는 0, ‘BBAAA’의 깊이는 2가 됩니다.(처음 나오는 A의 위치가 세 번째이지만 0부터 시작하므로 2가 됩니다.)
    ④ replyno(진짜 원 글의 번호)를 구합니다.
※ [주의!!!] 만약 답변 글(ⓐ)의 답변 글(ⓑ)일 경우에는 ⓐ의 number 값이 아닌 ⓐ의 replyno 값(즉, ⓐ의 원래 글)이 됩니다.
⑤ replyno가 같고 ‘깊이+1’번째 문자를 제외한 나머지 문자가 일치하는 글 중에서 가장 큰 reply값을 가진 글의 number를 구합니다.
⑥ ⑤에서 구한 number의 replyst 값에서, 깊이+1번째 문자를 구합니다.
⑦ ⑥에서 구한 위치의 다음 문자를 구합니다.
⑧ replyst 값에 깊이+1번째 문자를 ⑦에서 구한 문자로 바꿉니다.
⑨ 목록을 보여줄 때는 replyno를 내림차순으로 정렬한 상태에서 reply를 기준으로 오름차순 정렬합니다.


처음 봐서는 도저히 이해가 안 될 겁니다.
일단 위와 같은 규칙을 적용한다고 하고, 아래 내용을 봐 주세요.



  1. 첫 번째 글을 등록할 경우



    ① number는 자동 증가하므로 1이 됩니다.
    ② 답변 글이 아니므로 replyno의 값은 number와 같은 1이 됩니다.
    ③ 답변 글이 아니므로 replyst의 값은 ‘AAAAA’가 됩니다.

  2. 두 번째 글을 등록할 경우



    ① number는 자동 증가하므로 2가 됩니다.
    ② 답변 글이 아니므로 replyno의 값은 number와 같은 2가 됩니다.
    ③ 답변 글이 아니므로 replyst의 값은 ‘AAAAA’가 됩니다.

  3. 두 번째 글의 답변 글을 등록할 경우



    ① number는 자동 증가하므로 3이 됩니다.
    ② 원 글(number=2)의 replyst의 값은 ‘AAAAA’입니다.
    ③ 원 글의 깊이(처음 나오는 ‘A’)는 0입니다. (0부터 시작합니다.)
    ④ replyno(원 글의 번호)는 2가 됩니다.
    ⑤ replyno=2이고 깊이+1(=1)번째 문자를 제외한 나머지 문자(_AAAA)가 일치하는 글(하나밖에 없네요.) 중에서 가장 큰 reply값을 가진 글의 number=2입니다.
    ⑥ number=2의 replyst 값이 ‘AAAAA’인데, 깊이+1(=1)번째 문자가 ‘A’입니다.
    ⑦ ‘A’ 다음의 문자는 ‘B’입니다.
    ⑧ replyst 값은 ‘BAAAA’입니다.
    ⑨ 목록을 보여줄 때는 replyno를 내림차순으로 정렬한 상태에서 reply를 기준으로 오름차순 정렬합니다.

  4. 세 번째 글을 등록할 경우



    ① number는 자동 증가하므로 4가 됩니다.
    ② 답변 글이 아니므로 replyno의 값은 number와 같은 4가 됩니다.
    ③ 답변 글이 아니므로 replyst의 값은 ‘AAAAA’가 됩니다.

  5. 첫 번째 글(number=1)의 답변 글을 등록할 경우



    ① number는 자동 증가하므로 5가 됩니다.
    ② 원 글(number=1)의 replyst의 값은 ‘AAAAA’입니다.
    ③ 원 글의 깊이(처음 나오는 ‘A’)는 0입니다. (0부터 시작합니다.)
    ④ replyno(원 글의 번호)는 1이 됩니다.
    ⑤ replyno=1이고 깊이+1(=1)번째 문자를 제외한 나머지 문자(_AAAA)가 일치하는 글(역시 하나밖에 없네요.) 중에서 가장 큰 reply값을 가진 글의 number=1입니다.
    ⑥ number=1의 replyst 값이 ‘AAAAA’인데, 깊이+1(=1)번째 문자가 ‘A’입니다.
    ⑦ ‘A’ 다음의 문자는 ‘B’입니다.
    ⑧ replyst 값은 ‘BAAAA’입니다.
    ⑨ 목록을 보여줄 때는 replyno를 내림차순으로 정렬한 상태에서 reply를 기준으로 오름차순 정렬합니다.

  6. 두 번째 글의 답변 글(number=3)의 답변 글을 등록할 경우



    ① number는 자동 증가하므로 6이 됩니다.
    ② 원 글(number=3)의 replyst의 값은 ‘BAAAA’입니다.
    ③ 원 글의 깊이(처음 나오는 ‘A’)는 1입니다. (0부터 시작합니다.)
    ④ replyno(진짜 원 글의 번호)는 2가 됩니다.
    ※ [주의!!!] 답변형 게시판 Type1과 다릅니다.
    여기서 원 글은 number=3이 아닙니다. 비록 number=3의 답변글이기는 하지만, number=3의 글이 number=2의 글의 답변글이므로, number=3의 원 글인 number=2로 해야 합니다.
    ②와 ④에서의 원 글의 의미는 다릅니다. 그래서 다음부터 replyno를 ‘진짜 원 글’(^^)이라고 하겠습니다. 주의!!!!

    ⑤ replyno=2이고 깊이+1(=2)번째 문자를 제외한 나머지 문자(B_AAA)가 일치하는 글(nuber=3 하나밖에 없네요.) 중에서 가장 큰 reply값을 가진 글의 number=3입니다.
    ⑥ number=3의 replyst 값이 ‘BAAAA’인데, 깊이+1(=2)번째 문자가 ‘A’입니다.
    ⑦ ‘A’ 다음의 문자는 ‘B’입니다.
    ⑧ replyst 값은 ‘BBAAA’입니다.
    ⑨ 목록을 보여줄 때는 replyno를 내림차순으로 정렬한 상태에서 reply를 기준으로 오름차순 정렬합니다.

  7. 두 번째 글의 답변 글의 답변 글(number=6)의 답변 글을 등록할 경우



    ① number는 자동 증가하므로 8이 됩니다.
    ② 원 글(number=6)의 replyst의 값은 ‘BBAAA’입니다.
    ③ 원 글의 깊이(처음 나오는 ‘A’)는 2입니다. (0부터 시작합니다.)
    ④ replyno(진짜 원 글의 번호)는 2가 됩니다.
    ⑤ replyno=2이고 깊이+1(=3)번째 문자를 제외한 나머지 문자(AA_AA)가 일치하는 글(2,3,6) 중에서 가장 큰 reply값을 가진 글은 number=6입니다.
    ⑥ number=6의 replyst 값이 ‘BBAAA’인데, 깊이+1(=3)번째 문자가 ‘A’입니다.
    ⑦ ‘A’ 다음의 문자는 ‘B’입니다.
    ⑧ replyst 값은 ‘BBBAA’입니다.
    ⑨ 목록을 보여줄 때는 replyno를 내림차순으로 정렬한 상태에서 reply를 기준으로 오름차순 정렬합니다.

  8. 다시 두 번째 글(number=2)의 답변 글을 등록할 경우



    ① number는 자동 증가하므로 9가 됩니다.
    ② 원 글(number=2)의 replyst의 값은 ‘AAAAA’입니다.
    ③ 원 글의 깊이(처음 나오는 ‘A’)는 0입니다.
    ④ replyno(진짜 원 글의 번호)도 2가 됩니다.
    ⑤ replyno=2이고 깊이+1(=1)번째 문자를 제외한 나머지 문자(_AAAA)가 일치하는 글(2,3) 중에서 가장 큰 reply값을 가진 글은 number=3입니다.
    ⑥ number=3의 replyst 값
"쇼핑몰·홈페이지·오픈마켓
블로그·페이스북·이메일 등의 각종 마케팅 글쓰기,
각종 광고, 영업, 판매, 제안서, 전단지
반응율 3배×10배 이상 높이는 마법의 8단계 공식"
자세히보기

Comments

번호 제목 글쓴이 날짜 조회
3285 세션정보를 DB에 넣고 중복로그인 막고 사이트 통합로그인 13 김영철 01.13 16911
3284 [html] Form - 라디오버튼에서 value값 넘기기 99 단국강토 02.05 14690
3283 제가 사용하고 있는 마케팅프로그램입니다 댓글1 3 천지인 05.23 13188
3282 네이버 관련 바이럴마케팅 프로그램 총집함(카페/블로그/지식인 등) 3 천지인 05.15 13092
3281 관공서/회사접속 차단 해제 댓글8 3 초이스 05.13 12773
3280 엑셀 파일 합치기 매크로 댓글17 2 coruscate 09.14 11104
3279 파일1입니다 url helper 댓글1 2 비비드바비 04.29 10856
3278 파일2입니다 2 비비드바비 04.29 10474
3277 [펌] 제11강 - ADO(Active Database Object) - Database Access Component Cobol vs C#-1 M 최고의하루 12.23 9483
3276 Aqua data studio 한글 깨짐 설정 13 김영철 01.29 9020
3275 history.back() 시 폼데이터 유지하기 13 김영철 01.15 7583
3274 [ ASP ] url 정보의 파라메터 및 쿼리스트링 자유롭게 조정하는 함수 M 최고의하루 12.19 7466
3273 플래시에서 책장 넘기는 효과 내는 학습 자료 M 최고의하루 12.26 7419
3272 MBTI 테스트지 + 테스트파일 + 결과 댓글35 2 비비드바비 04.29 7231
3271 XML을 해야 하는 이유 13 김영철 01.29 6997
3270 gva.bgdb 인증크랙 댓글4 M 최고의하루 12.18 6792
3269 테이블 넓이 고정 태그:자동 줄 바꿈(break-all, nowrap, fixed) 99 단국강토 02.05 6586
열람중 PHP 답변형 게시판 / 자료실 /PHP강좌 13 김영철 01.13 6169
3267 PDF-Pro 4 free 2 춘몽 11.22 6128
3266 award bios 어워드 바이오스 설정법 M 최고의하루 12.18 5897
3265 퍼지는 빛 만들기 | 포 토 샵 [중급] 10 액션쟁이 01.05 5763
3264 ntdll.dll 오류 해결방법 M 최고의하루 01.12 5729
3263 Edit Plus html 내보내기 예제 M 최고의하루 12.20 5727
3262 [ MySQL ] MySQL 5 한글 UTF8 한글 깨짐 분석 (Windows 용) M 최고의하루 12.04 5727
3261 ASP의 EXECUTE, EVAL 사용하기 M 최고의하루 12.23 5683
3260 log 분석 13 김영철 01.14 5636
3259 메일 수신 확인 체크 소스입니다 13 김영철 01.13 5624
3258 화면캡쳐하는 방법, 동영상 이나오는 화면 캡쳐시 안보이는 부분 나오게 하는 방법 M 최고의하루 12.26 5591
3257 The Oracle + PHP Cookbook :: Oracle/PHP 환경의 LOB 처리 13 김영철 01.14 5588
3256 엑셀 자동달력 서식 댓글5 M 최고의하루 12.18 5541
마케팅
특별 마케팅자료
다운로드 마케팅자료
창업,경영
기획,카피,상품전략
동기부여,성취