5. PHP 게시판 만들기, write 제작 2

2015. 4. 2. 23:51
저자 : Kurien

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

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


지금까지 write 입력 폼을 만들었으니, 이제부터는 write에 입력한 값을 업데이트 하는 부분을 만들어 보겠습니다.

파일명은 write_update.php라는 이름으로 만들었습니다.


파일명을 만들때는 파일이 어떤 기능을 하는지를 쉽게 알 수 있는 방법이 좋다고 하기도 하고,

직접 경험해본 결과도 직관적인 이름이 편집하기 더 편했네요.


그럼 먼저 아래의 파일을 다운로드 받아봅시다.


20150402_project.zip


이번에도 다른 부분에 수정사항이 있는데요,

dbconfig.php의 맨 윗부분에 header('Content-Type: text/html; charset=utf-8');이라는 코드를 추가했습니다.


이 부분은 PHP에서의 인코딩을 설정해주는데,

html을 사용한다면 head 태그 내부에 <meta charset='utf-8'>이란 태그를 넣어줌으로써 인코딩을 utf-8로 설정할 수 있지만,

만약 html을 사용하지 않는 이번 페이지(write_update.php) 같은 경우는 인코딩을 설정할 수가 없기 때문에 php에서 설정을 해줍니다.


dbconfig.php에 넣어주는 이유는 모든 페이지에 공통으로 들어가는(include) 부분이기 때문이죠.

만약 일반적인 홈페이지라면 common.php와 같은 모든 페이지에 공통으로 들어가기 위해 만드는 파일에 header와 같은 함수를 설정해줍니다.


서론은 여기까지 하고 write_update.php를 보도록 하죠.


<?php

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


$bID = $_POST['bID'];

$bPassword = $_POST['bPassword'];

$bTitle = $_POST['bTitle'];

$bContent = $_POST['bContent'];

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



$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 . '"))';


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

if($result) { // query가 정상실행 되었다면,

$msg = "정상적으로 글이 등록되었습니다.";

$bNo = $db->insert_id;

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

} else {

$msg = "글을 등록하지 못했습니다.";

?>

<script>

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

history.back();

</script>

<?php

}


?>

<script>

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

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

</script>


전에 만들어놓은 write.php에서 입력 되는 부분은 bID, bPassword, bTitle, bContent 총 네 가지였습니다.

먼저 write_update.php에서도 db를 사용하므로 dbconfig.php를 include 해주시구요,


write.php에서 넘어온 값을 변수에 넣어주는 부분이 있습니다.


write.php의 form 태그에서 method=""속성의 값을 get으로 했다면 $_GET['변수'],

post라고 했다면 $_POST['변수']를 통해서 변수를 얻을 수 있는데요,

만약 $_REQUEST['변수']를 하게되면 get이든, post든 상관없이 모든 값을 받아올 수 있습니다.


그렇다면 $_REQUEST['변수']를 쓰면 편한게 아니냐고 생각하시는 분들이 계실텐데요,

프로그래밍에서는 여러가지의 길이 존재하면 좋은게 아닙니다.

물론 필요할 때 맞춰 쓰는 건 괜찮지만, 될 수 있으면 제작하는 사람이 귀찮은 편이 보안상에는 좋죠.

php의 설정중에는 $_POST['변수']와 같은걸 따로 설정할 필요 없이 $변수로 바로 변경 되게하는 설정이 있는데요,


이렇게 되면 보안적으로는 완전히 떨어지게 되므로 쓰지 않으시는 편이 좋습니다.

물론 현재는 보안적으로는 전혀 신경쓰지 않은 게시판을 만들고 있지만 보안 부분도 다뤄볼 생각입니다.


다시 본론으로 돌아와서 $bID, $bPassword, $bTitle, $bContent라는 변수를 선언했으니 다음 부분을 보겠습니다.

$date라는 변수를 선언 했는데, 여기에는 date('Y-m-d H:i:s')라는 값이 저장됩니다.

이 값은 현재 시간을 나타내주는 함수니까, $date에는 글을 등록한 시간이 저장됩니다.


이제 $sql 변수에 sql문을 작성합니다.

write_update는 글 쓰기를 의미하니 db에는 insert문을 사용해야겠죠?

insert문은 insert into 테이블명 (column 명) values(값);이나, insert into 테이블명 values(값);과 같이 사용되는데요.

저는 더 길게 표현하는 전자를 사용했습니다.


만약 column명을 함께 표현하게 되면 나중에 수정하게 될 때 어떤 부분에 어떤 값이 들어가는지 쉽게 알 수 있거든요.

sql 구문을 만드는 방식은 개인 취향이므로 알아서 하시면 될 것 같네요.


db에서 테이블을 만들 때 primary auto_increment 값을 줬던 column은 값을 입력할 때 null만을 입력해도 자동으로 입력됩니다.

숫자(int) 형식은 0, 10, 23 이런식으로 주변에 감싸는 부분이 없어야 하구요.

문자(char, varchar, date 등) 형식은 ""(큰따옴표)나 ''(작은따옴표)가 있어야합니다.


그리고 또 다른 형식인 password('비밀번호')가 있습니다.

password는 mysql의 자체 함수로 입력받은 문자열을 해시화 해주는데요.


해시라는 것은 원래 불필요한 정보를 모은다는 뜻이 있지만, 암호화에서는 다시 풀어낼 수 없는 암호를 만든다고 생각하시면 됩니다.

만약 kurien이라는 암호를 입력했을 경우에 password() 함수는 *19BA5733867E9DB038840C6FE88CF1007D61E97B라는 해시를 출력합니다.


저 정보를 가지고 다시 풀어낼 방법은 없습니다.

그럼 절대 안뚫리는게 아닌가?라는 생각을 하신 분들에게 말씀 드리자면 저 암호를 다시 kurien이라는 단어로 바꿀 수 있는 방법 자체는 없지만,

password()라는 함수를 누구나 쓸 수 있는 만큼 그 기능을 가지고 각 값을 해시화 해서 데이터베이스에 저장해두고 확인 하는 방법이 존재합니다.

자세한 부분은 나중에 다루도록 하고, 일단은 password() 함수만을 사용해서 하도록 하겠습니다.


이제 insert문을 완성 했으니, $db->query를 통해서 쿼리를 보냅니다.

만약 정상적으로 쿼리가 전달 되었다면 $result에 TRUE가 들어가고, 실패하면 FALSE 값이 들어갑니다.


if문을 이용해서 $result가 정상적으로 동작했다면 $msg에 정상적으로 등록되었다고 적고, $db->insert_id;를 $bNo 변수에 넣어줍니다.

$db->insert_id;는 이번에 insert 된 자료의 auto_increment 값을 다시 반환해주게 되는데,

이 값을 가지고 게시글이 나오는 화면으로 이동 시켜야 하기 때문이죠.


$bNo을 얻었다면, $replaceURL 변수에 './view.php?bno=' . $bNo; 값을 저장합니다.

이 부분은 $bNo(기본 키)를 가지고 게시글을 보여주는 페이지로 이동하기 위한 URL을 저장하는 부분이구요.

view.php는 다음 포스팅에서 다룰 부분입니다.


그 다음 if문을 빠져 나오게 되고 최하단에 있는 <script>alert($msg); location.replace($replaceURL);</script>이 실행됩니다.

성공했다는 메시지와 게시글을 보여줄 페이지로 이동하는 스크립트죠.



만약 위에서 $result에 FALSE가 입력 되었다면 DB 전송이 실패했다는 말이므로 등록에 실패했다는 메시지를 $msg에 저장합니다.

그 다음 <script>alert($msg); history.back();</script>을 통해 $msg를 출력하고, 이전 화면으로 돌아가줍니다.


여기까지 write_update.php 부분이였습니다.

사이사이 주제가 딴대로 새버려서 글이 조금 길어졌지만, 배우면서 필요한 부분이라고 생각되어서 적었던 부분입니다.

어려운 부분이 있다면 질문 부탁드리구요!

잘못된 부분은 거리낌 없이 지적 부탁드립니다!

TAG ,
  1. 이전 댓글 더보기
  2. 튼튼 2015.10.18 12:40  댓글주소  수정/삭제  댓글쓰기

    감사합니다!

  3. Leakim 2016.02.05 12:28  댓글주소  수정/삭제  댓글쓰기

    안녕 하세요 .kurien님,
    게시판 만드는 방법 쉽게 설명해주셔서 정말 감사하게 보고있어요.

    질문이 있습니다.
    sql문에서 values 값을 입력할때,
    values(null, "' . $bTitle . '", "' . $bContent . '", "' . $date . '", 0, "' . $bID . '", password("' . $bPassword . '"))';

    값을 " ' .$값 . ' " 처럼 큰따옴표/작은따옴표 그리고 '.' 로 감싼 이유가 있을까요?

    • Kurien 2016.02.07 22:47 신고  댓글주소  수정/삭제

      예를 들어서 "' . $bTitle . '" 이 있을 때 $bTitle이 Kurien이라는 단어라고 하면, 이 부분이 mysql로 전달 될 때는 "Kurien" 이라는 문자열이 전달됩니다.
      만약 ' . $bTitle . '이였다면 Kurien이라고 전달이 되지만, 해당 단어는 문자열일 때 사용 되는 큰 따옴표 혹은 작은 따옴표로 감싸져있지 않기 때문에 오류가 출력될 것이구요.

      쉽게 말해서 ""는 mysql에 전달 될 부분이고, ' . . '는 php 상에서 변수를 표현하기 위해서 사용 됩니다.
      다르게 사용하는 방법으로는 "{$bTitle}"도 "' . $bTitle . '"과 같은 결과를 출력합니다.

  4. djpark 2016.03.23 10:52  댓글주소  수정/삭제  댓글쓰기

    설명이 쉽고 상세해서 이해안되는 곳이 없을만큼 좋네요!
    감사합니다.

  5. 시로시로 2016.07.19 13:40  댓글주소  수정/삭제  댓글쓰기

    디비는 연결이 되었는데 디비 안으로 입력한값이 저장이 되질 않네요. ㅜㅜ 글이 등록 되었습니다 라고 알림창이 뜨고나서 다음 view 페이지로 넘어가는데 view창에도 입력한 내용이 나오지 않고 디비에도 저장이 되질 않습니다. 저는 임의로 db부분을 <?php
    header('Content-Type: text/html; charset=utf-8');

    //------------------------디비연결
    $db_ip = "localhost";
    $db_user = "**********";
    $db_pw = "**********";
    $db_name = "************";

    $conn = mysqli_connect($db_ip, $db_user, $db_pw, $db_name);

    if(mysqli_connect_errno($conn)) {
    echo "데이터베이스 연결 실패:" . mysqli_connect_error();
    } else {
    echo "성공!";
    }

    //-------------------------디비연결



    $sql = " select * from board_test ";

    $result = mysqli_query($conn,$sql);


    ?>

    이런식으로 바꿨는데 이부분이 문제인지 궁금합니다..

    아, 객체지향부분을 절차적으로 다 바꿨습니다.

    • Kurien 2016.07.21 21:51 신고  댓글주소  수정/삭제

      남겨주신 내용만으로는 오류가 발생할만한 문제는 없어보이네요.
      kurien92@gmail.com으로 전체 소스 남겨주시면 확인해보고 답변 드릴께요^^

  6. 직딩1 2016.07.26 11:48  댓글주소  수정/삭제  댓글쓰기

    안녕하세요. 쭉 잘 보고 있습니다. 질문 하나 남깁니다.

    $bID = $_POST['bID'];
    $bPassword = $_POST['bPassword'];
    $bTitle = $_POST['bTitle'];
    $bContent = $_POST['bContent'];
    $date = date('Y-m-d H:i:s');

    이 부분에서 경고가 뜹니다.

    Do not Access Superglobal $_POST Array Directly.
    Use some filtering functions instead (e.g. filter_input(), conditions with is_*0 functions, etc.).

    정상 등록 알럿창은 뜹니다만... 도움 부탁드립니다. ㅠㅠ

    • 직딩1 2016.07.26 11:50  댓글주소  수정/삭제

      동일 댓글 4개가 연속으로 달렸는데 수정은 되지만 삭제가 안 됩니다... ㅠㅠ

    • Kurien 2016.07.26 12:48 신고  댓글주소  수정/삭제

      일단 삭제 프로그램 부분은 제가 수정할 수 있는 부분이 아니라서 중복된 내용만 지웠구요.

      해당 오류는 저도 처음 보는 오류인데, 아마도 xampp?를 사용했을 때 나오는 오류인 듯 하네요.

      오류 내용으로 봐선 $_POST['변수']처럼 사용하지 말고 filter_input()과 같은 필터링이 가능한 함수를 거쳐 사용하라는 말인 듯 싶습니다.

      http://php.net/manual/kr/function.filter-input.php
      위의 문서를 보고 사용하시면 될 것 같네요.

    • 직딩1 2016.07.26 16:36  댓글주소  수정/삭제

      알려주신 링크대로 했더니 경고가 사라지고 알럿창만 예쁘게 떴습니다. 감사합니다! ^^

  7. 컴공 2016.11.11 17:41  댓글주소  수정/삭제  댓글쓰기

    아니 이렇게 좋고 쉬운글 보고 어렵다느니 외계어라느니..!! 말도안됩니다.

    Kurien 님 정말 감사합니다.

    책 출판하셔도 이것보다 더 쉽게 설명하는 책은 없을 듯 합니다. 진짜 짱..

  8. 감사해요 2017.02.03 15:16  댓글주소  수정/삭제  댓글쓰기

    정말이해가 잘되요.... 짱짱!!!

  9. Hust 2017.02.24 15:26  댓글주소  수정/삭제  댓글쓰기

    처음 공부중이라 필요한부분을 최소한으로 할려고 글 6번까지만 제가 코딩을 했는데요 우선 write.php는 화면에 출력이 잘되고 write_update.php 여기로 넘어가는데 빈화면만뜨네요 그러고 view.php도 마찬가지로 빈화면이떠요 그러고 원래 update되고 view로바로넘어가는거아닌가요? 아직초보여서 힘드네요 답변부탁드립니다

  10. kakoku13 2017.03.17 15:54  댓글주소  수정/삭제  댓글쓰기

    PHP 게시판 만들기, write 제작 1까지 잘 되고 있다가 여기서 막혔답니다ㅠㅠ
    아이디, 비빌번호, 제목,내용을 쓰고 작성을 누르면
    글을 등록하지 못했습니다 라고 팝업창이 뜬답니다. 어디서 부터 잘못됬을까요?

    • Kurien 2017.03.23 09:30 신고  댓글주소  수정/삭제

      제가 올린 코드로는 정상적으로 올라갑니다.
      단순히 안된다고만 말씀하시면 저도 뭐라고 답변해드릴 수가 없어요.
      코드를 올려주신다던지, DB 구조를 살펴보셔야 할 듯 하네요.

  11. TyphoonHacker 2017.04.02 09:12  댓글주소  수정/삭제  댓글쓰기

    아무리 예제 소스라고 하지만 이걸 그대로 사용하시는 사람들이 있을거같은데
    소스가 너무 취약한거같습니다 조금이나마 보안에 관해 언급해주셨으면 하는 ...

    • Kurien 2017.04.03 15:31 신고  댓글주소  수정/삭제

      이 글을 작성할 때 보안에 대한 걱정이 없었어서 그 점을 간과했네요. 빠른 시일 내에 주의하라는 내용 추가하도록 하겠습니다.

  12. Sakura 2017.05.12 02:10  댓글주소  수정/삭제  댓글쓰기

    글 업데이트 소스

    <html>
    <head>
    <meta charset="utf-8">
    </head>
    </html>
    <?
    $connect=mysql_connect("localhost", "root", "apmsetup")or
    die("SQL서버에 연결할 수 없습니다!");
    mysql_select_db("php_db", $connect);

    $b_id = $_POST['b_id'];
    $b_pw = $_POST['b_pw'];
    $b_title = $_POST['b_title'];
    $b_content = $_POST['b_content'];

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


    $sql = 'insert into free_board (b_num, b_title, b_content, b_date, b_eye, b_id, b_pw)
    values(null, "' . $b_title . '", "' . $b_content . '", "' . $date . '", 0, "' . $b_id . '", "' . $b_pw . '"';

    $result = mysql_query($sql, $connect);
    if($result) { // query가 정상실행 되었다면,
    $$msg = "정상적으로 글이 등록되었습니다.";
    $b_num = $connect->insert_id;
    $replaceURL = './board_view.php?b_num=' . $b_num;
    // $replaceURL = './view.php?bno=' . $b_num;
    }else{
    $msg = "글을 등록하지 못했습니다.";
    ?>
    <script>
    alert("<? echo $msg ?>");
    history.back();
    </script>
    <?
    }

    ?>
    <script>
    alert("<?php echo $msg?>");
    location.replace("<? echo $replaceURL ?>");
    </script>



    글쓰기 소스에서도 input태그 name들 전부다 b_id, b_pw, b_title, b_content로 줬는데도 불구하고 자꾸 글이 안올라가져요 ㅠㅠ

  13. 한지민 2019.05.13 15:00  댓글주소  수정/삭제  댓글쓰기

    잘 보고있어요

  14. 또또 2019.10.18 20:16  댓글주소  수정/삭제  댓글쓰기

    실습따라하는 중입니다. 혹시 write_update에서 post값은 잘 넘어오는데, mysql로 안넘어가서 고생하는 분 있으시면, 비밀번호를 어렵게 설정해보면 될 수도 있습니다. 최신버전 mysql은 password()함수에도 패스워드생성규칙을 적용하는지 검사하는군요. 세부사항은 https://heartbleed.tistory.com/86링크의 4번항목 참고하세요. 정보남기는 김에 원작자님께 감사하는 말씀도 드리고 싶네요. 덕분에 많이 배우고 있습니다.

  15. 예진 2020.10.07 15:49  댓글주소  수정/삭제  댓글쓰기

    지금까지 좋은 설명 덕분에 잘 따라왔는데 실습따라하는 중 오류가 생겨 댓글 남깁니다. 모든 코드를 같게 했는데도 "글을 등록하지 못했습니다." 가 뜨면서 글 등록이 되지 않습니다. 데이터베이스로 직접 등록시에는 잘 올라가는데 글 수정이나 글쓰기가 안됩니다ㅠㅠ 어느부분이 문제일까요?

  16. 라시나 2022.04.27 23:33  댓글주소  수정/삭제  댓글쓰기

    자애로운 ♩두형이 스파이더맨 벽지까지 맞춰주고 가셨네
    구토들아 구톡방 돌리지마라 ㅋㅋ
    날두 신경 쓸 시간에 느그들 주인님이나 걱정해라 ㅋ
    오늘 인터뷰했는데(당사펌) 이랬음
    2. 윌리안, 2013 (£31.5m)



    이들 중 가장 비싼 영입이다. 2013년 1월에 영입된 [ http://xooxma.com ] 윌리안은 안지에서 11경기 출장에 그쳤고, 그 해 여름 £30m에 첼시로 이적했다.



    3. 사무엘 에투, 2011 (£24.3m)



    가장 비싼 건 아니지만, 확실히 이들 중 가장 미친 딜이다. 에투는 안지에서 세후 연봉 [ http://xooxa.xyz ] €20m을 받으며 세계 축구에서 가장 높은 소득을 자랑하는 선수가 되었다. 그는 73경기에서 26골을 넣었다.



    4. 알렉산드르 코코린, 2013 (£17.1m)



    2013년 여름에 영입한 높은 평가를 받았던 이 러시아 [ http://xooxb.xyz ] 공격수는 안지에서 총 0경기에 출전했고 약 한 달 후 예산 삭감으로 인해 디나모 모스크바로 팔려나갔다. 그는 현재 ACF 피오렌티나에서 뛰고 있다.



    2011년부터 2013년까지 안지 마하치칼라의 미친 돈♪♩♩을 기억하며 - 4.ren.jpg [기브미스포츠] 2011년부터 2013년까지 안지 마하치칼라의 미친 돈♪♩♩을 기억하며

  17. 코카티비 2022.05.17 11:26  댓글주소  수정/삭제  댓글쓰기

    스포츠중계 LIVE 코카티비 cokatv.com 가입x 무료웹툰 성인자료 분석정보 구글검색 "코카티비" 기프트콘/제휴업체머니/승무패 이벤트

  18. 코카티비 2022.05.18 13:17  댓글주소  수정/삭제  댓글쓰기

    스포츠중계 LIVE 코카티비 cokatv.com 가입x 무료웹툰 성인자료 분석정보 구글검색 "코카티비" 기프트콘/제휴업체머니/승무패 이벤트

  19. 레플리카 2022.05.18 20:01  댓글주소  수정/삭제  댓글쓰기

    텔레그램@tmsj9 이미테이션도매 레플래카도매 레플리카사이트제젝 홍콩명품사이트제작 이미테이션사이트제작 홍콩명품도매

  20. 코카티비 2022.05.20 20:29  댓글주소  수정/삭제  댓글쓰기

    스포츠중계 LIVE 코카티비 cokatv.com 가입x 무료웹툰 성인자료 분석정보 구글검색 "코카티비" 기프트콘/제휴업체머니/승무패 이벤트

  21. 세바스 2022.05.23 05:08  댓글주소  수정/삭제  댓글쓰기

    3부리그

    세바스티안 뵈셀 (27): 1. FC 자르브뤼켄에서 [ http://xooxa.xyz ] 할리스체스 FC로 (수비수, 2022년 여름까지 계약)

    필리프 줄레흐네어(31) : 클럽이 없다가 할레슈 FC로 (공격수, 2022년 여름까지 계약)

    잘렌 호킨스 (21): FC 잉골슈타트에서 FC 자르브뤼켄로 (미드필더, 여름까지 임대)

    야밀 지베르트(19): 포르투나 뒤셀도르프에서 빅토리아 [ http://xooxb.xyz ] 쾰른으로 (수비수, 여름까지 임대)

    마이크 파이겐스판(26): 헤센 카셀에서 SV 메펜으로 (공격수, 옵션과 함께 2022년 여름까지 계약)

    케빈 라우후트 (32): SGV 프라이베르크 풋볼에서 빅토리아 쾰른으로 (공격수, 계약 기간 미상)

    앤서니 시어(26) : 클럽이 없다가 FSV 즈비카우로 (미드필더, 2022년 여름까지 계약)


    도미니크 코더(21) : 카를스루에 SC에서 발트호프 [ http://xooxc.xyz ] 만하임으로 (공격수, 여름까지 임대)