8. PHP 게시판 만들기, write 제작 4

2015.04.08 22:28
저자 : Kurien

주의: 본 게시판은 보안을 생각하지 않고 만들어졌으므로 실제로 사용되어서는 안되는 코드입니다.

공부할 때 게시판이 이처럼 동작한다는 정도로만 이해해주세요.


오늘은 전 포스팅에서 설명하지 못한 write_update.php에 대해서 적어보겠습니다.

어제와 같은 파일을 받아주세요!


20150407_project.zip


write_update.php를 열어봅시다.


<?php

require_once("../dbconfig.php");


//$_POST['bno']이 있을 때만 $bno 선언

if(isset($_POST['bno'])) {

$bNo = $_POST['bno'];

}


//bno이 없다면(글 쓰기라면) 변수 선언

if(empty($bNo)) {

$bID = $_POST['bID'];

$date = date('Y-m-d H:i:s');

}


//항상 변수 선언

$bPassword = $_POST['bPassword'];

$bTitle = $_POST['bTitle'];

$bContent = $_POST['bContent'];


//글 수정

if(isset($bNo)) {

//수정 할 글의 비밀번호가 입력된 비밀번호와 맞는지 체크

$sql = 'select count(b_password) as cnt from board_free where b_password=password("' . $bPassword . '") and b_no = ' . $bNo;

$result = $db->query($sql);

$row = $result->fetch_assoc();

//비밀번호가 맞다면 업데이트 쿼리 작성

if($row['cnt']) {

$sql = 'update board_free set b_title="' . $bTitle . '", b_content="' . $bContent . '" where b_no = ' . $bNo;

$msgState = '수정';

//틀리다면 메시지 출력 후 이전화면으로

} else {

$msg = '비밀번호가 맞지 않습니다.';

?>

<script>

alert("<?php echo $msg?>");

history.back();

</script>

<?php

exit;

}

//글 등록

} else {

$sql = 'insert into board_free (b_no, b_title, b_content, b_date, b_hit, b_id, b_password) values(null, "' . $bTitle . '", "' . $bContent . '", "' . $date . '", 0, "' . $bID . '", password("' . $bPassword . '"))';

$msgState = '등록';

}


//메시지가 없다면 (오류가 없다면)

if(empty($msg)) {

$result = $db->query($sql);

//쿼리가 정상 실행 됐다면,

if($result) {

$msg = '정상적으로 글이 ' . $msgState . '되었습니다.';

if(empty($bNo)) {

$bNo = $db->insert_id;

}

$replaceURL = './view.php?bno=' . $bNo;

} else {

$msg = '글을 ' . $msgState . '하지 못했습니다.';

?>

<script>

alert("<?php echo $msg?>");

history.back();

</script>

<?php

exit;

}

}


?>

<script>

alert("<?php echo $msg?>");

location.replace("<?php echo $replaceURL?>");

</script>


이번에도 추가된 부분은 빨간색으로 바꿔뒀습니다.

차근차근 알아보겠습니다.


//$_POST['bno']이 있을 때만 $bno 선언

if(isset($_POST['bno'])) {

$bNo = $_POST['bno'];

}


//bno이 없다면(글 쓰기라면) 변수 선언

if(empty($bNo)) {

$bID = $_POST['bID'];

$date = date('Y-m-d H:i:s');

}


먼저 이 부분에서도 write.php처럼 $_POST['bno']이 있는지 확인합니다.

write.php에서와 다른 점이라면 $_GET['bno']에서 $_POST['bno']으로 바뀌었다는 점 뿐이겠네요.

get과 post의 차이는 아실거라고 생각하고 넘어가겠습니다.


그 아래 보시면 if(empty($bno)) {}이라는 조건문이 있는데, isset과 달리 이번에는 $bNo이라는 변수에 값이 없다면 출력되는 부분입니다.

$bNo이 없는건 글을 쓸 때 뿐이므로 $bNo이 없을 때만 글을 쓸 때 필요한 $bID와 $date를 선언합니다.


//글 수정

if(isset($bNo)) {

//수정 할 글의 비밀번호가 입력된 비밀번호와 맞는지 체크

$sql = 'select count(b_password) as cnt from board_free where b_password=password("' . $bPassword . '") and b_no = ' . $bNo;

$result = $db->query($sql);

$row = $result->fetch_assoc();

//비밀번호가 맞다면 업데이트 쿼리 작성

if($row['cnt']) {

$sql = 'update board_free set b_title="' . $bTitle . '", b_content="' . $bContent . '" where b_no = ' . $bNo;

$msgState = '수정';

//틀리다면 메시지 출력 후 이전화면으로

} else {

$msg = '비밀번호가 맞지 않습니다.';

?>

<script>

alert("<?php echo $msg?>");

history.back();

</script>

<?php

exit;

}

//글 등록

} else {


이번엔 이 부분을 설명하겠습니다.

자주 봤던 isset($bNo)을 이용해서 글 수정 상태일 때만 실행되는 부분입니다.

먼저 select문을 이용해서 board_free 테이블 내에 같은 b_no(글번호), 같은 b_password(글 비밀번호)가 존재하는지 찾습니다.


만약 존재한다면 $row['cnt']의 값은 1이 출력되겠죠?

b_no은 기본키로 중복된 값이 있을 수 없으니깐요,


여기서 글이 없거나, b_password와 password($bPassword)의 값이 일치하지 않는다면 $row['cnt']가 0이 되는데요.

없는 글번호라면 일반적인 사용자가 write_update.php까지 접근할 수 없습니다.

직접 form을 변형해서 write_update.php로 post로 던져주지 않는 이상은요.


자세한건 나중에 보안쪽에서 함께 다루도록 하구요, 어쨌든 정상적인 과정이라면 비밀번호가 틀릴 때 0이라는 값이 나오게 되므로

else를 이용해서 $msg에 '비밀번호가 맞지 않습니다.' 라는 값을 넣어주고 $msg를 출력해줬습니다.


그리고 전에 빠진 부분이 있었는데, "exit" 이 키워드를 써야만 프로그램이 여기서 종료 됩니다.

만약 exit를 빼고 넘어가버리면 프로그램이 중지되지 않고 끝까지 실행된 후 종료됩니다.

필수 사항이니 꼭 넣어주세요!


정상적으로 1이 나오게 된다면 비밀번호가 맞다는 말이므로 update문을 이용해서 수정된 내용을 갱신시켜줍니다.


그리고 $msgState라는 변수를 새로 선언 했는데,

update문을 사용했다는 말은 수정을 했다는 말이므로 뒤에 나올 메시지의 값을 수정으로 출력할 때 쓰려고 적었습니다.


글 수정이 아니라면 else를 통해 글 등록 부분으로 넘어갑니다.

기존에 만든 부분이지만 여기서도 조금 수정한 부분이 있습니다.


$msgState = '등록';


이 $msgState도 글 수정에 있던 $msgState = '수정';과 같은 역할을 합니다.

아래 나올 내용에서 더 알아보고 여기선 넘어갑시다.


//메시지가 없다면 (오류가 없다면)

if(empty($msg)) {}


이 부분은 지금 보니 딱히 필요한 부분은 아닌데요.

나중에 <script>alert("<?php echo $msg?>"); history.back();</script> 이 부분을 한번에 사용할 생각이긴 한데

일단은 그냥 넘어가셔도 될 것 같습니다.


여기까지 왔다면 update문이든 insert 문이든 상관 없이 $result = query 전송 부분이 실행됩니다.

전에 설명 했듯이 쿼리 결과가 성공이라면 $result = TRUE가 되구요,

실패하면 FALSE가 되겠죠.


성공을 했다면 아래의 코드가 실행됩니다.


$msg = '정상적으로 글이 ' . $msgState . '되었습니다.';

if(empty($bNo)) {

$bNo = $db->insert_id;

}

$replaceURL = './view.php?bno=' . $bNo;


여기서 $msgState의 용도가 나오네요.

만약 수정을 했다면 $msg는 '정상적으로 글이 수정되었습니다.'라는 문장이 될 것이고,

글을 썼다면 '정상적으로 글이 등록되었습니다.'라는 문장이 됩니다.


아래 있는 if(empty($bNo)) {}은 아까 본것처럼 $bNo의 값이 없다면(글쓰기라면) 실행하는 부분입니다.

글쓰기였다면 $bNo = $db->insert_id;를 실행해서 $bNo의 값을 받아옵니다.


그 다음 $replaceURL을 작성해주죠.


$msg = '글을 ' . $msgState . '하지 못했습니다.';


만약 $result가 FALSE라면 글을 수정 or 등록하지 못했습니다. 라는 메시지를 보여주고 이전 화면으로 되돌아갑니다.


<script>

alert("<?php echo $msg?>");

location.replace("<?php echo $replaceURL?>");

</script>


정상적으로 실행 되었던 상태라면 위의 코드를 가지고 view.php 화면으로 돌아가게 되는거죠.


게시판도 하나의 프로그램이라서 나름 복잡하다면 복잡합니다.

이해하기 힘든 부분이 있을 수도 있구요.


나름 설명 길게 열심히 달았다고 생각하니, 꼭 몇번 읽어보시구요.

그래도 이해가 잘 안된다 싶으면 댓글 남겨주세요!


더 좋은 방법, 틀린 부분이 있다면 지적은 환영입니다!

TAG ,
  1. ParkSoDa 2015.09.09 21:46 신고  댓글주소  수정/삭제  댓글쓰기

    글 정말 잘봤습니다! 정말 유용한 블로그네요 ㅎㅎ..
    음..그런데말이지요 제가 이글을 따라서 써보았는데 글 등록부분인
    $sql = 'insert into board_free (b_no, b_title, b_content, b_date, b_hit, b_id, b_password) values(null, "' . $bTitle . '", "' . $bContent . '", "' . $date . '", 0, "' . $bID . '", password("' . $bPassword . '"))';

    부분에서

    Parse error: syntax error, unexpected '' . $bTitle . '' (T_CONSTANT_ENCAPSED_STRING), expecting ',' or ';' in
    이런 오류가 뜨더군요! 해결방법을 어떻게하죠??..

  2. hyeok 2015.10.15 19:52 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요. 좋은 글 잘 보고 있습니다.
    중간에 문제가 계속나서 질문 하겠습니다 ㅠ.
    글수정하는 부분에서 select 하는 sql 문에서 문제가 발생하더군요.
    b_password=password("' . $bPassword . '") and b_no = ' . $bNo; 이부분 이대로 사용하면 cnt는 항상 0이 들어가서 b_password="'.$bPassword.'") and -------- 이런식으로 바꾸어야 하던데 무슨 문제 때문에 이런것 인가요?
    저는 php 5.6 // mysql 5.6.20 입니다.

  3. cha 2016.01.20 01:59 신고  댓글주소  수정/삭제  댓글쓰기

    혹시 관리자 페이지처럼 비밀번호를 사용하지 글을 수정하려면 어떻게 하면 괜찮을까요?

    • Kurien 2016.02.03 10:35 신고  댓글주소  수정/삭제

      "혹시 관리자 페이지처럼 비밀번호를 사용하지 않고 글을 수정하려면 어떻게 하면 괜찮을까요?" 라고 이해하고 답변 달아드리겠습니다.

      방법 자체는 간단합니다.
      세션을 사용해서 해당 세션이 존재한다면 비밀번호를 검증하는 부분을 넘어가주시면 됩니다.

  4. WarmBoi 2016.05.19 21:09 신고  댓글주소  수정/삭제  댓글쓰기

    if(isset($bNo)) {
    //수정 할 글의 비밀번호가 입력된 비밀번호와 맞는지 체크
    $sql = 'select count(password) as cnt from board where password="' . $bPassword . '" and b_no = ' . $bNo;
    $result = $db->query($sql);
    $row = $result->fetch_assoc();

    //비밀번호가 맞다면 업데이트 쿼리 작성
    if($row['cnt']) {
    $sql = 'update board set title="' . $bTitle . '", content="' . $bContent . '" where num = ' . $bNo;
    $msgState = '수정';
    //틀리다면 메시지 출력 후 이전화면으로
    } else {
    $msg = '비밀번호가 맞지 않습니다.';
    ?>
    <script>
    alert("<?php echo $msg?>");
    history.back();
    </script>
    <?php
    exit;
    }

    //글 등록
    } else {
    $sql = 'select count(num) as cnt from board';
    $result = $db->query($sql);
    $row = $result->fetch_assoc();
    if($row['cnt']){
    $num = $result +1;
    } else {
    $num = 1;
    }

    $sql = 'insert into board (num, title, content, wdate, count, writer, password) values("' . $num . '", "' . $bTitle . '", "' . $bContent . '", "' . $date . '", 0, "' . $bID . '", "' . $bPassword . '")';
    $msgState = '등록';
    }

    //메시지가 없다면 (오류가 없다면)
    if(empty($msg)) {
    $result = $db->query($sql);

    //쿼리가 정상 실행 됐다면,
    if($result) {
    $msg = '정상적으로 글이 ' . $msgState . '되었습니다.';
    if(empty($bNo)) {
    $bNo = $db->insert_id;
    }
    $replaceURL = 'board_view.html?bno=' . $bNo;
    } else {
    $msg = '글을 ' . $msgState . '하지 못했습니다.';

    데이터 베이스에서 b_no 대신 num으로 사용하고 있고 not null 입니다. 그래서 코드 부분을 약간 수정했는데요. 1번이랑 2번 까지는 글쓰기가 되는데 3번째부터 글쓰기가 되지 않습니다.
    어떤 부분을 고쳐야 할까요...
    ps. //글 등록 바로 아래 부분 고쳤습니다.

    • Kurien 2016.05.27 09:13 신고  댓글주소  수정/삭제

      답변이 너무 늦었네요 죄송합니다.

      $sql = 'select count(num) as cnt from board';
      $result = $db->query($sql);
      $row = $result->fetch_assoc();
      if($row['cnt']){
      $num = $result +1;
      }

      올려주신 위 부분에서 $num = $result + 1이 아니라 $num = $row['cnt'] + 1로 쓰시려고 하신게 아닌가 싶네요.

      그리고 위와 같은 방식은 문제가 생길 수 있습니다.

      될 수 있으면 num 열에 auto_increment를 줘서 DB에서 기본 키 값을 설정해주시는 편이 좋습니다.

  5. 2pro 2016.06.23 12:14 신고  댓글주소  수정/삭제  댓글쓰기

    'select count(b_password) as cnt from board_free where b_password=password("' . $bPassword . '") and b_no = ' . $bNo; <<-- 이 셀렉트 쿼리문에서 = password 는 무얼 가르키는 건가요? write에서 td class = password를 지정해준건가요?
    저는 지금 게시판을 응용해서 다른걸 만들고 있는데 ..
    select count(name) as nm from board_free where name='이름 ' and b_no = 1;
    mysql에서 sql문을 직접 작성해보았습니다 위와 같이
    그럼 cnt부분이 1이 정상적으로 나오는데 php소스 가서 실행해보면 자꾸 에러가 나네요...
    그래서 저 password 부분이 궁금해져서 이러케 댓글 남겨요
    제가 write 부분에서 클래스나 id나 혹은 다른 무언가를 선언안해준것인가 .. 생각되네여
    그래서 클래스나 id , name은 선언해줘 봤는데 해결 못했어요..
    'select count(b_password) as cnt from board_free where b_password=password("' . $bPassword . '") and b_no = ' . $bNo; 이러케 해서 수정을 눌러보면 변수 선언해준 $bPassword에서 에러가 나네요
    password를 지워버리면 틀리다는 팝업창이 나오고요

    결론은 password의 의미가 궁금합니다.

    • Kurien 2016.06.23 12:36 신고  댓글주소  수정/삭제

      password("' . $bPassword . '")
      여기서 password()는 mysql의 함수로 $bPassword의 값을 알아볼 수 없는 값으로 변경해주는(해시) 함수입니다.

      오류가 발생하는건 아마도 다른 이유일 듯 싶네요.

    • 2pro 2016.06.23 13:06 신고  댓글주소  수정/삭제

      아 ~~ 밑에 인서트부분을 보고 알아챘어요 . password가 먼지...
      저는 현재 수정하려는 행위를 하고 있는 글쓴이ID와 수정글의 글쓴이ID가 같으면 수정되도록 하려고 하고 있거든요 ㅎㅎ
      정독했다고 생각했는데 아직 한참 모자르네요 ^^; 답변 감사합니다!
      해보다가 또 막히면 여쭈러 오겠습니다.^^ 점심 맛있게 드세요~

  6. 김양우 2016.09.29 16:40 신고  댓글주소  수정/삭제  댓글쓰기

    그대로 사용해서 board_free디비도 만들었는데 자꾸 글을 등록하지 못했다는 오류만 뜨네요ㅠㅠ
    b_title, b_content, b_no, b_date, b_hit, b_id, b_password 이렇게 디비에 넣었는데 뭐가 문제죠
    ㅠㅠ

    • Kurien 2016.09.30 14:42 신고  댓글주소  수정/삭제

      말씀하신 부분만으로는 오류를 알아낼 방법이 없습니다.

      kurien92@gmail.com으로 제작중이신 프로그램을 보내주시면 확인 후 답변 드릴께요.

  7. Rothko 2016.11.08 19:22 신고  댓글주소  수정/삭제  댓글쓰기

    혹시 몰라서 남깁니다. (제가 해딩한부분!)
    mysqli_insert_id() 쓰시는 분들 주의하세요 , 구글링에서 mysqli_insert_id()는 마지막 쿼리의 사용된 id(AUTO_INCREMENT)를 반환하는데
    마지막 쿼리가 insert 또는 update문이 아니거나, 수정된 필드가 AUTO_INCREMENT가 아닌경우 '0'을 반환합니다.!!!
    if문이 괜히 있었던게 아니었네요,,,, 수정,작성 상관없이 모두 mysqli_insert_id()로 받을라다가 헤맸네요 ;;;;

    • Kurien 2016.11.14 09:42 신고  댓글주소  수정/삭제

      코드가 개판이지만 ㅠㅠ
      그래도 나름 생각하며 짰었던거에요 ㅋ

      아마 그 당시 나름의 이유가 있어서 저렇게 해뒀을거라고 생각합니다!