본문 바로가기
Programming

[PHP 강좌] 37. 관계형 게시판 만들기 5 - 글수정, 댓글쓰기, 글삭제

by Mizix 2010. 2. 11.
반응형
이제 관계형 게시판의 마지막입니다.

지난시간에 글을 작성하고 목록을 보고 글을 보는데까지 만들어 봤습니다.

오늘은 글을 수정하고 또 댓글을 달고 글을 삭제한느 부분을 배워보도록 하겠습니다.

먼저 글을 수정하는 소스를 보겠습니다.

<?
// 1. 공통 인클루드 파일
include ("./include.php");

// 2. 로그인 안한 회원은 로그인 페이지로 보내기
if(!$_SESSION[user_id]){
    ?>
    <script>
        alert("로그인 하셔야 합니다.");
        location.replace("board_login.php");
    </script>
    <?
}

// 3. 글 데이터 불러오기
$sql = "select * from tb_board where b_idx = '".$_GET[b_idx]."'";
$result = sql_query($sql);
$data = mysql_fetch_array($result);

// 4. 글이 없으면 메세지 출력후 되돌리기
if(!$data[b_idx]){
    ?>
    <script>
        alert("존재하지 않는 글입니다.");
        history.back();
    </script>
    <?
}

// 5. 본인의 글이 아니면 메세지 출력후 되돌리기
if($data[m_id] != $_SESSION[user_id]){
    ?>
    <script>
        alert("본인의 글이 아닙니다.");
        history.back();
    </script>
    <?
}

// 5. 입력 HTML 출력
?>
<br/>
<table style="width:1000px;height:50px;border:5px #CCCCCC solid;">
    <tr>
        <td align="center" valign="middle" style="font-zise:15px;font-weight:bold;">글수정</td>
    </tr>
</table>
<br/>
<form name="bWriteForm" method="post" action="./board_modify_save.php" style="margin:0px;">
<input type="hidden" name="b_idx" value="<?=$data[b_idx]?>">
<table style="width:1000px;height:50px;border:0px;">
    <tr>
        <td align="center" valign="middle" style="width:200px;height:50px;background-color:#CCCCCC;">글제목</td& gt;
        <td align="left" valign="middle" style="width:800px;height:50px;"><input type="text" name="b_title" style="width:780px;" value="<?=$data[b_title]?>"></td>
    </tr>
    <tr>
        <td align="center" valign="middle" style="width:200px;height:200px;background-color:#CCCCCC;">글내용< /td>
        <td align="left" valign="middle" style="width:800px;height:200px;">
        <textarea name="b_contents" style="width:800px;height:200px;"><?=$data[b_contents]?></textarea>
        </td>
    </tr>
    <!-- 4. 글쓰기 버튼 클릭시 입력필드 검사 함수 write_save 실행 -->
    <tr>
        <td align="center" valign="middle" colspan="2"><input type="button" value=" 글수정 " onClick="write_save();">&nbsp;&nbsp;&nbsp;<input type="button" value=" 뒤로가기 " onClick="history.back();"></td>
    </tr>
</table>
</form>
<script>
// 5.입력필드 검사함수
function write_save()
{
    // 6.form 을 f 에 지정
    var f = document.bWriteForm;

    // 7.입력폼 검사

    if(f.b_title.value == ""){
        alert("글제목을 입력해 주세요.");
        return false;
    }

    if(f.b_contents.value == ""){
        alert("글내용을 입력해 주세요.");
        return false;
    }

    // 8.검사가 성공이면 form 을 submit 한다
    f.submit();

}
</script>
[board_modify.php 소스]

글쓰기와 거의 비슷하고 다른점은 글의 데이터를 불러와서 검사후 입력폼들에 넣어 준다는 것입니다.

HTML 내용은 글쓰기와 동일합니다.

단 글번호를 hiddeb 타입의 input 오브젝트에 넘겨줄수 있게 하였고 각 데이터들을 해당 입력폼에 보여지게 해서 수정하게 하였습니다.

[실행화면]



저장하는 소스인 board_modify_save.php 소스는 다음과 같습니다.

<?
// 1. 공통 인클루드 파일
include ("./include.php");

// 2. 로그인 안한 회원은 로그인 페이지로 보내기
if(!$_SESSION[user_id]){
    ?>
    <script>
        alert("로그인 하셔야 합니다.");
        location.replace("board_login.php");
    </script>
    <?
}

// 3. 넘어온 변수 검사
if(trim($_POST[b_idx]) == ""){
    ?>
    <script>
        alert("없는 글입니다.");
        history.back();
    </script>
    <?
    exit;
}

if(trim($_POST[b_title]) == ""){
    ?>
    <script>
        alert("글제목을 입력해 주세요.");
        history.back();
    </script>
    <?
    exit;
}

if(trim($_POST[b_contents]) == ""){
    ?>
    <script>
        alert("글내용을 입력해 주세요.");
        history.back();
    </script>
    <?
    exit;
}

// 4. 글 데이터 불러오기
$sql = "select * from tb_board where b_idx = '".$_POST[b_idx]."'";
$result = sql_query($sql);
$data = mysql_fetch_array($result);

// 5. 글이 없으면 메세지 출력후 되돌리기
if(!$data[b_idx]){
    ?>
    <script>
        alert("존재하지 않는 글입니다.");
        history.back();
    </script>
    <?
}

// 6. 본인의 글이 아니면 메세지 출력후 되돌리기
if($data[m_id] != $_SESSION[user_id]){
    ?>
    <script>
        alert("본인의 글이 아닙니다.");
        history.back();
    </script>
    <?
}

// 7. 글저장
$sql = "update tb_board set b_title = '".addslashes(htmlspecialchars($_POST[b_title]))."', b_contents = '".addslashes(htmlspecialchars($_POST[b_contents]))."' where b_idx = '".$_POST[b_idx]."'";
sql_query($sql);

// 8. 글목록 페이지로 보내기
?>
<script>
alert("글이 저장 되었습니다.");
location.replace("./board_list.php");
</script>
[board_modify_save.php 소스]

이 파일도 글쓰기 저장과 비슷하지만 글번호로 데이터를 불러와 검사하는 부분과

저장시 update로 저장한 후 글쓰기때처럼 b_num은 별도로 수정을 해주지 않습니다.

다음은 댓글쓰기입니다.

<?
// 1. 공통 인클루드 파일
include ("./include.php");

// 2. 로그인 안한 회원은 로그인 페이지로 보내기
if(!$_SESSION[user_id]){
    ?>
    <script>
        alert("로그인 하셔야 합니다.");
        location.replace("board_login.php");
    </script>
    <?
}

// 3. 글 데이터 불러오기
$sql = "select * from tb_board where b_idx = '".$_GET[b_idx]."'";
$result = sql_query($sql);
$data = mysql_fetch_array($result);

// 4. 글이 없으면 메세지 출력후 되돌리기
if(!$data[b_idx]){
    ?>
    <script>
        alert("존재하지 않는 글입니다.");
        history.back();
    </script>
    <?
}

// 5. 댓글이 가능한지 검사
// 5-1. 이 글의 단계가 몇단계 인지 검사후 3단계면 댓글 불가
if(strlen($data[b_reply]) == 3){
    ?>
    <script>
        alert("더이상 댓글을 쓸수가 없습니다.");
        history.back();
    </script>
    <?
}

// 5-2 이글에 달린 댓글의 마지막 댓글이 몇번째인지 검사

$sql2 = "select * from tb_board where b_num = '".$data[b_num]."' and b_reply like '".$data[b_reply]."%' order by b_reply desc limit 1";
$result2 = sql_query($sql2);
$data2 = mysql_fetch_array($result2);

if(substr($data2[b_reply], strlen($data[b_reply]), 1) == "Z"){
    ?>
    <script>
        alert("더이상 댓글을 쓸수가 없습니다.");
        history.back();
    </script>
    <?
}

// 6. 입력 HTML 출력
?>
<br/>
<table style="width:1000px;height:50px;border:5px #CCCCCC solid;">
    <tr>
        <td align="center" valign="middle" style="font-zise:15px;font-weight:bold;">댓글쓰기</td>
    </tr>
</table>
<br/>
<form name="bWriteForm" method="post" action="./board_reply_save.php" style="margin:0px;">
<input type="hidden" name="b_idx" value="<?=$data[b_idx]?>">
<table style="width:1000px;height:50px;border:0px;">
    <tr>
        <td align="center" valign="middle" style="width:200px;height:50px;background-color:#CCCCCC;">글제목</td& gt;
        <td align="left" valign="middle" style="width:800px;height:50px;"><input type="text" name="b_title" style="width:780px;" value=""></td>
    </tr>
    <tr>
        <td align="center" valign="middle" style="width:200px;height:200px;background-color:#CCCCCC;">글내용< /td>
        <td align="left" valign="middle" style="width:800px;height:200px;">
        <textarea name="b_contents" style="width:800px;height:200px;"></textarea>
        </td>
    </tr>
    <!-- 4. 글쓰기 버튼 클릭시 입력필드 검사 함수 write_save 실행 -->
    <tr>
        <td align="center" valign="middle" colspan="2"><input type="button" value=" 댓글쓰기 " onClick="write_save();">&nbsp;&nbsp;&nbsp;<input type="button" value=" 뒤로가기 " onClick="history.back();"></td>
    </tr>
</table>
</form>
<script>
// 5.입력필드 검사함수
function write_save()
{
    // 6.form 을 f 에 지정
    var f = document.bWriteForm;

    // 7.입력폼 검사

    if(f.b_title.value == ""){
        alert("글제목을 입력해 주세요.");
        return false;
    }

    if(f.b_contents.value == ""){
        alert("글내용을 입력해 주세요.");
        return false;
    }

    // 8.검사가 성공이면 form 을 submit 한다
    f.submit();

}
</script>
[board_reply.php 소스]

댓글을 쓰기 전에 글 데이터를 불러서 댓글을 쓰는것이 가능한지를 검사합니다.

5번이 검사하는 부분인데요.

5-1 은 부모글 즉 댓글을 달려고 하는 글의 b_reply 의 글자수를 구합니다.
strlen 은 글자수를 구해주는 함수입니다.
부모글의 댓글 단계가 3단계 즉 b_reply 가 3글자이면 더 이상 댓글을 달수 없으니 불가능하다는 메세지를 출력한 후 되돌립니다.

5-2 는 부모글의 댓글 중 가장 아래쪽에 달린 댓글의 b_reply를 검사해서 Z 를 넘어가면 더 댓글을 달수 없다는 메세지를 보냅니다.
즉 글중에서 b_num 이 같은글 (댓글이나 부모글이겠지요.) 이고 b_reply가 부모글의 b_reply를 포함한 글을 거꾸로 정렬시켜 제일 마지막글의 데이터를 구합니다.

b_reply like '내용%' 는 b_reply 가 내용으로 시작하는 것을 말합니다.
like 는 like '%내용%' (내용을 포함하는것), '내용%' (내용으로 시작하는것), '%내용' (내용으로 끝나는것) 처럼 사용할 수 있습니다.

부모글의 b_reply 다음글자가 Z 이면 더이상 글을 쓸수 없다는 메세지를 보냅니다. substr 은 전에 배웠을겁니다.

그리고 부모글을 b_idx 에 hidden으로 넣어 글을 작성해 저장하는 페이지로 넘깁니다.

다음은 저장하는 페이지 입니다.

<?
// 1. 공통 인클루드 파일
include ("./include.php");

// 2. 로그인 안한 회원은 로그인 페이지로 보내기
if(!$_SESSION[user_id]){
    ?>
    <script>
        alert("로그인 하셔야 합니다.");
        location.replace("board_login.php");
    </script>
    <?
}

// 3. 부모글 데이터 불러오기
$sql = "select * from tb_board where b_idx = '".$_POST[b_idx]."'";
$result = sql_query($sql);
$data = mysql_fetch_array($result);

// 4. 부모글이 없으면 메세지 출력후 되돌리기
if(!$data[b_idx]){
    ?>
    <script>
        alert("존재하지 않는 글입니다.");
        history.back();
    </script>
    <?
}

// 5. 댓글이 가능한지 검사
// 5-1. 부모글의 단계가 몇단계 인지 검사후 3단계면 댓글 불가
if(strlen($data[b_reply]) == 3){
    ?>
    <script>
        alert("더이상 댓글을 쓸수가 없습니다.");
        history.back();
    </script>
    <?
}

// 5-2 부모글에 달린 댓글의 마지막 댓글이 몇번째인지 검사

$sql2 = "select * from tb_board where b_num = '".$data[b_num]."' and b_reply like '".$data[b_reply]."%' order by b_reply desc limit 1";
$result2 = sql_query($sql2);
$data2 = mysql_fetch_array($result2);

$last_reply_char = substr($data2[b_reply], strlen($data[b_reply]), 1);
if($last_reply_char == "Z"){
    ?>
    <script>
        alert("더이상 댓글을 쓸수가 없습니다.");
        history.back();
    </script>
    <?
}

// 6. 넘어온 변수 검사
if(trim($_POST[b_title]) == ""){
    ?>
    <script>
        alert("글제목을 입력해 주세요.");
        history.back();
    </script>
    <?
    exit;
}

if(trim($_POST[b_contents]) == ""){
    ?>
    <script>
        alert("글내용을 입력해 주세요.");
        history.back();
    </script>
    <?
    exit;
}

// 7. b_num 과 b_reply 만들기
$b_num = $data[b_num];
if($last_reply_char){
    $b_reply = $data[b_reply].chr(ord($last_reply_char) + 1);
}else{
    $b_reply = $data[b_reply]."A";
}

// 8. 글저장
$sql = "insert into tb_board set b_num = '".$b_num."', b_reply = '".$b_reply."', m_id = '".$_SESSION[user_id]."', m_name = '".$_SESSION[user_name]."', b_title = '".addslashes(htmlspecialchars($_POST[b_title]))."', b_contents = '".addslashes(htmlspecialchars($_POST[b_contents]))."', b_regdate = now()";
sql_query($sql);


// 9. 글목록 페이지로 보내기
?>
<script>
alert(" 글이 저장 되었습니다.");
location.replace("./board_list.php");
</script>
[board_reply_save.php 소스]

댓글을 달수 있는지 검사까지는 board_reply.php와 같습니다.

7번은 b_num 과 b_reply 만드는 부분인데요.
b_num 은 부모글의 b_num과 같으므로 부모글의 b_num을 사용합니다.
b_reply 는 부모글의 댓글 중 가장 마지막 댓글의 단계표시문자
즉 $last_reply_char = substr($data2[b_reply], strlen($data[b_reply]), 1); 을 구한 후
댓글이 없으면 A를 부모글의 b_reply에 합쳐서 적어주고
댓글이 있으면 마지막 댓글의 단계표시문자를 ord() 와 chr() 함수를 이용해 다음글자를 구한 후 부모글의 b_reply 에 합쳐줍니다.
즉 ord()로 글자의 아스키번호를 구합니다. 여기서 구해진 아스키번호에 1을 더해 다음 문자의 아스키 번호를 구한 후
chr() 함수로 해당 아스키번호의 문자를 구합니다.

조금 복잡하지만 php.net 에서 각 함수의 사용법을 숙지하시면 이해하기 더 쉬워지실 겁니다.

이렇게 해서 아래 리스트 화면의 실행 화면처럼 댓글을 작성할 수 있습니다.



이제 글을 삭제하는 파일을 만들어 보겠습니다.

글을 삭제시는 댓글까지 모두 삭제합니다.

<?
// 1. 공통 인클루드 파일
include ("./include.php");

// 2. 로그인 안한 회원은 로그인 페이지로 보내기
if(!$_SESSION[user_id]){
    ?>
    <script>
        alert("로그인 하셔야 합니다.");
        location.replace("board_login.php");
    </script>
    <?
}

// 3. 글 데이터 불러오기
$sql = "select * from tb_board where b_idx = '".$_GET[b_idx]."'";
$result = sql_query($sql);
$data = mysql_fetch_array($result);

// 4. 글이 없으면 메세지 출력후 되돌리기
if(!$data[b_idx]){
    ?>
    <script>
        alert("존재하지 않는 글입니다.");
        history.back();
    </script>
    <?
}

// 5. 본인의 글이 아니면 메세지 출력후 되돌리기
if($data[m_id] != $_SESSION[user_id]){
    ?>
    <script>
        alert("본인의 글이 아닙니다.");
        history.back();
    </script>
    <?
}

// 6. 글 삭제하기
$sql_delete = "delete from tb_board where b_num = '".$data[b_num]."' and b_reply like '".$data[b_reply]."%'";
sql_query($sql_delete);


// 7. 글목록 페이지로 보내기
?>
<script>
alert("글이 삭제 되었습니다.");
location.replace("./board_list.php");
</script>
[board_delete.php 소스]

5번까지 글의 존재와 자기 글인지를 검사합니다.

6번에서 삭제할때 b_num이 같고 b_reply가 삭제하는 글과 같은 문자로 시작하는 글들을 모두 지웁니다.

이러면 아래단계의 댓글까지 다 지워집니다.

where 절 이하는 댓글 검사시에도 사용하였던 구문입니다.

이제 관계형 게시판을 만드는것을 다 배우셨습니다.

다음시간부터는 이 게시판을 더 발전시켜서 제로보드나 그누보드처럼 게시판을 설치하고 게시판의 모양과기능을 설정하는 설치형 게시판을 배워보도록 하겠습니다.

반응형