[PHP] 게시판 만들기 - 댓글 기능 구현 ② (ajax 활용)
저번 실습에서는 LiveRe에서 제공하는 댓글 서비스를 이용하여 댓글 기능을 기존의 프로젝트에 추가해봤습니다.
이번시간에는 직접 첫 실습에서 설계한 DB를 기반으로 ajax 통신을 이용해 다음과 같이 댓글 기능을 구현해보도록 하겠습니다.
실습은 다음과 같은 순서로 진행됩니다.
1. 댓글 목록 페이지 디자인을 위한 reply.css
2. 댓글 목록 페이지 및 기능 구현, 모달창 구현 read.php
3. 댓글 기능 이벤트 구현(ajax) reply.js
4. 댓글 작성 기능 구현 reply_ok.php
5. 댓글 삭제 기능 구현 reply_delete.php
1. 댓글 목록 페이지 디자인
/* 댓글 css */
.reply_view {
width:900px;
margin-top:100px;
word-break:break-all;
}
.dat_view {
font-size: 14px;
padding:10px 0 15px 0;
border-bottom: solid 1px gray;
}
.dat_ins {
margin-top:50px;
}
.dat_edit_t{
width:520px;
height:70px;
position: absolute;
top: 40px;
}
.rep_con {
width:700px;
height: 56px;
}
.rep_btn {
position: absolute;
width:100px;
height:56px;
font-size:16px;
margin-left: 10px;
}
해당 코드를 진행중인 프로젝트의 css 폴더에 새로운 파일을 하나 만들어 작성해줍니다.
2. 댓글 목록 페이지 및 기능
read.php에 위에서 작성한 css 파일을 적용시키기 위해 다음과 같이 설정을 해주고
<link rel="stylesheet" href="css/reply.css">
저번 LiveRe를 이용해서 댓글 기능을 구현했을 때와 마찬가지로 수정, 삭제 버튼 아래에 댓글 목록을 가져오기 위해 다음과 같이 코드를 추가해줍니다.
<!-- 댓글 불러오기 -->
<div class="container">
<div class="reply_view">
<h3 style="padding:10px 0 15px 0; border-bottom: solid 1px gray;">댓글목록</h3>
<?php
$sql3=mq("select
*
from
reply
where
con_num='".$bno."'
order by
idx desc
");
while($reply=$sql3->fetch_array()){
?>
<div class="dat_view">
<div><b><?=$reply['name']?></b></div>
<div class="dap_to comt_edit"><?php echo nl2br("$reply[content]"); ?></div>
<div class="rep_me dap_to"><?=$reply['date']?></div>
<div class="rep_me rep_menu">
<a class="dat_del_btn" href="#">삭제</a>
</div>
</div>
<?php } ?>
</div>
</div>
<!-- 댓글 불러오기 끝 -->
댓글을 불러오는 로직은 게시물 목록을 가져왔을 때의 로직과 동일합니다. 이전 실습을 잘 따라오셨다면 어렵지 않게 이해가 가능할 것이라고 생각해 자세한 설명은 생략하고 reply 테이블의 컬럼들이 각각 어떤 의미를 가지는지에 대한 정보만 다시 링크로 남겨두도록 하겠습니다.
이번에는 댓글 작성 폼을 만들어보도록 하겠습니다.
<!-- 댓글 달기 -->
<div class="dat_ins">
<input type="hidden" name="bno" class="bno" value=<?=$bno?>>
<input type="hidden" name="dat_user" id="dat_user" class="dat_user" value=<?=$userid?>>
<input type="password" name="dat_pw" id="dat_pw" class="dat_pw" size="15" placeholder="비밀번호">
<div style="margin-top:10px;">
<textarea name="content" class="rep_con" id="rep_con"></textarea>
<button id="rep_btn" class="rep_btn">댓글</button>
</div>
</div>
댓글 작성 폼의 input 값들을 hidden 속성으로 설정하여 앞단에서 보여지지 않게 설정한 후 이 정보들을 ajax 통신을 이용하여 댓글 작성 기능 로직을 처리하는 reply_ok.php 로 보낼 예정입니다.
※ input 태그의 value에 해당하는 값들이 ajax 통신을 통해 보내집니다. 위의 코드를 보면 현재 세션의 아이디를 값으로 넘기는 것을 볼 수 있는데, 이는 댓글을 작성한 아이디가 누구였는지를 표시하기 위함입니다.
다음으로 각각의 댓글 목록에서 삭제 버튼을 눌렀을 때 나오는 모달창을 구현해보도록 하겠습니다.
<!-- 댓글 삭제 모달창 구현 -->
<div class="modal fade" id="rep_modal_del">
<div class="modal-dialog">
<div class="modal-content">
<!-- header -->
<div class="modal-header">
<!-- 닫기(x) 버튼 -->
<button type="button" class="close" data-dismiss="modal">×</button>
<!-- header title -->
<h4 class="modal-title"><b>댓글 삭제</b></h4>
</div>
<!-- body -->
<div class="modal-body">
<form method="post" id="modal_form" action="reply_delete.php">
<input type="hidden" name="rno" value="<?=$reply['idx'];?>" /><input type="hidden" name="b_no" value="<?=$bno;?>">
<p>비밀번호 <input type="password" name="pw" /> <input type="submit" class="btn btn-primary" value="확인" /></p>
</form>
</div>
</div>
</div>
</div>
<!-- 댓글 삭제 모달창 구현 끝 -->
해당 모달창은 비밀글을 구현하는 실습에서 해봤던 것과 동일합니다. hidden 값으로 댓글의 idx 값, 게시판의 idx 값을 그리고 DB에 저장된 패스워드와 비교하기 위해 패스워드를 입력받아 post 방식으로 reply_delete.php로 데이터를 전송합니다. (자세한 내용은 다음 링크를 참고합니다.)
다음은 read.php에서 수정한 내용을 전부 결합한 코드입니다.
<!-- 댓글 불러오기 -->
<div class="container">
<div class="reply_view">
<h3 style="padding:10px 0 15px 0; border-bottom: solid 1px gray;">댓글목록</h3>
<?php
$sql3=mq("select
*
from
reply
where
con_num='".$bno."'
order by
idx desc
");
while($reply=$sql3->fetch_array()){
?>
<div class="dat_view">
<div><b><?=$reply['name']?></b></div>
<div class="dap_to comt_edit"><?php echo nl2br("$reply[content]"); ?></div>
<div class="rep_me dap_to"><?=$reply['date']?></div>
<div class="rep_me rep_menu">
<a class="dat_del_btn" href="#">삭제</a>
</div>
</div>
<!-- 댓글 삭제 모달창 구현 -->
<div class="modal fade" id="rep_modal_del">
<div class="modal-dialog">
<div class="modal-content">
<!-- header -->
<div class="modal-header">
<!-- 닫기(x) 버튼 -->
<button type="button" class="close" data-dismiss="modal">×</button>
<!-- header title -->
<h4 class="modal-title"><b>댓글 삭제</b></h4>
</div>
<!-- body -->
<div class="modal-body">
<form method="post" id="modal_form" action="reply_delete.php">
<input type="hidden" name="rno" value="<?=$reply['idx'];?>" /><input type="hidden" name="b_no" value="<?=$bno;?>">
<p>비밀번호 <input type="password" name="pw" /> <input type="submit" class="btn btn-primary" value="확인" /></p>
</form>
</div>
</div>
</div>
</div>
<!-- 댓글 삭제 모달창 구현 끝 -->
<?php } ?>
<!-- 댓글 달기 -->
<div class="dat_ins">
<input type="hidden" name="bno" class="bno" value=<?=$bno?>>
<input type="hidden" name="dat_user" id="dat_user" class="dat_user" value=<?=$userid?>>
<input type="password" name="dat_pw" id="dat_pw" class="dat_pw" size="15" placeholder="비밀번호">
<div style="margin-top:10px;">
<textarea name="content" class="rep_con" id="rep_con"></textarea>
<button id="rep_btn" class="rep_btn">댓글</button>
</div>
</div>
</div>
</div>
<!-- 댓글 불러오기 끝 -->
3. 댓글 기능 이벤트(ajax)
read.php 에 다음과 같이 자바스크립트 파일을 참조하게끔 설정하고
<script src="./js/reply.js"></script>
진행중인 프로젝트의 js 폴더에 다음과 같이 reply.js를 만들어줍니다.
/* 댓글 작성 이벤트(ajax) */
$(function(){
$("#rep_btn").click(function(){
$.ajax({ //비동기통신방법, 객체로 보낼때{}사용
url : "reply_ok.php",
type : "post",
data : {
"bno" : $(".bno").val(),
"dat_user" : $(".dat_user").val(),
"dat_pw" : $(".dat_pw").val(),
"rep_con" : $(".rep_con").val(),
},
success : function(data){
alert("댓글이 작성되었습니다");
location.reload();
}
});
});
/* 댓글 삭제 이벤트 */
$(".dat_del_btn").click(function(){
$("#rep_modal_del").modal();
});
});
'#rep_btn' 은 read.php의 댓글 작성 폼에서 댓글을 달기 위한 버튼의 id 이름을 의미합니다. 댓글 작성 폼에서 댓글 버튼을 누르면 위와 같이 JSON 형식으로 reply_ok.php에 데이터를 전송합니다. 작업이 성공하면 댓글이 작성되었다는 alert창이 뜨고 location.reload() 함수를 통해 자동으로 새로고침 처리가 됩니다.
새로고침을 하는 이유는 댓글 작성이 완료되고 난 후 새로고침을 눌러야만 삭제 버튼을 눌렀을 때 이벤트가 발생하는 오류가 존재해서 이와 같이 처리를 해주었습니다.
'.dat_del_btn'은 댓글 목록에 있는 삭제 버튼의 class 이름을 의미합니다. 해당 삭제 버튼을 누르면 모달창 이벤트가 나타납니다.
4. 댓글 작성 기능
<?php
include './config.php';
include './db/db_con.php';
$bno = $_POST['bno'];
$userpw = password_hash($_POST['dat_pw'], PASSWORD_DEFAULT);
$sql = mq("insert
reply
set
con_num = '".$bno."',
name = '".$_POST['dat_user']."',
pw = '".$userpw."',
content = '".$_POST['rep_con']."'
");
?>
ajax 통신을 통해 전달된 데이터들을 받아서 DB에 insert 쿼리문을 이용하여 저장합니다. 회원가입 실습에서 비밀번호를 DB에 저장할 때 보안을 위해 암호화하여 저장했던 것처럼, 댓글의 비밀번호도 동일하게 암호화 처리를 해줍니다.
5. 댓글 삭제 기능
<?php
include './config.php';
include './db/db_con.php';
// hidden의 값 rno를 받아와 그 값에 해당하는 idx 에 대한 reply 테이블 정보 가져오기
$rno = $_POST['rno'];
$sql = mq("select
*
from
reply
where
idx='".$rno."'
");
$reply = $sql->fetch_array();
// hidden의 값 b_no를 받아와 그 값에 해당하는 idx 에 대한 board 정보 가져오기
$bno = $_POST['b_no'];
$sql2 = mq("select
*
from
board
where
idx='".$bno."'
");
$board = $sql2->fetch_array();
$pwk = $_POST['pw']; // 모달창에서 입력한 비밀번호
$rpw = $reply['pw']; // reply 테이블에 저장된 해쉬값
/* 비밀번호를 db의 해쉬값과 비교, 세션값과 db의 name을 비교 */
if((password_verify($pwk, $rpw)) && ($userid == $reply['name']))
{
// 테이블 reply에서 인덱스값이 $rno인 값을 찾아 삭제
$sql = mq("delete
from
reply
where
idx='".$rno."'
");
?>
<script>
alert("댓글이 삭제 되었습니다.");
</script>
<meta http-equiv="refresh" content="0 url=/gimal/read.php?idx=<?=$bno?>">
<?php
}else{ ?>
<script>
alert('본인의 댓글이 아니거나 비밀번호가 틀립니다');
history.back();
</script>
<?php } ?>
post 방식으로 넘어온 데이터들을 받아 해당하는 댓글의 번호를 DB에서 존재하나 확인 후 그 값을 가져오고 거기에 저장된 패스워드와 post로 넘어온 패스워드를 비교하고 현재 세션의 아이디와 DB에서 가져온 아이디의 값이 같은지 확인한 후 이 둘을 모두 만족한다면 해당하는 댓글 번호를 가진 레코드를 삭제하게끔 delete 쿼리문을 작동합니다.
삭제가 완료되면 댓글이 삭제되었다는 alert창이 뜨고 만약 본인의 댓글이 아니거나 패스워드가 틀리면 다른 alert창이 뜨게끔 구현했습니다.
해당 내용이 잘 이해가 되지 않는다면 그 전 실습을 참고하시길 바랍니다.
https://transferhwang.tistory.com/48
다음은 댓글 삭제 기능을 구현한 결과 입니다.
이렇게 ajax를 이용한 댓글 기능 구현을 마무리했습니다. 이번 실습은 여태까지 실습을 진행하면서 익혔던 다양한 내용들을 종합한 실습이였다고 생각하기에 더 의미있는 실습이라고 생각합니다.
여기까지가 제가 PHP를 이용해 간단한 게시판 프로젝트를 진행했던 내용이었습니다. 추후에 내용 추가는 상황을 봐서 올려보도록 하겠습니다. (요즘은 PHP보다 스프링을 공부중이기때문에...)
부족한 내용이지만 잘 따라와주신 모든 분들 감사합니다 :)
잘못된 부분이나 실습을 진행하면서 궁금한 점은 댓글로 남겨주세요 ㅎㅎ
※ 완성 코드는 공지사항에 있는 깃헙 주소에서 확인할 수 있습니다.
PHP 게시판 만들기 시리즈 👇