게시판 좋아요 기능은 원래있던 DB Table에 likes라는 column을 추가하여 추천을 누르게 되면 값이 하나씩 증가하도록 하면 된다.
다만 여기서 문제점으로는 그렇게되면 좋아요를 같은사람이 무한하게 누를 수 있다는것이다. 따라서 다음과 같은 검증과정이 필요하다
1. 로그인 여부
2. 좋아요 클릭 여부.
로그인 여부는 간단하게 검사가 가능하다. 세션 변수를 확인하면 된다.
다만 좋아요 클릭 여부는 서버에 UserID, Userid_id중 하나를 저장해야 한다.
UserID는 물론 중복검사를 통해서 중복되는 아이디가 없겠지만 int 형식의 UserID_id가 더 빠르고 저장공간도 덜 차지할것이라 생각되므로 이를 사용하겠다.
DB의 컬럼에는 배열을 저장하기 위해서 JSON형식으로 선언해주었다. 물론 JSON형식이므로 php형식으로 항상 배열을 encoding decoding 해주어야 한다.
좋아요를 누를 경우 만약 누른적이 없으면 좋아요가 증가하고 누른적이 있으면 좋아요가 다시 내려가도록 update 쿼리문을 이용하였다.
<?php
require_once '../tool/session_open.php';
// require_once '../tool/chack_er.php';
if(!$_SESSION['loggedin']){
echo "<script> alert('로그인이 필요합니다.'); </script>";
exit;
}
require_once '../tool/db_conn.php';
$ID_NUM = $_GET["id"];
$content_query = "SELECT * FROM board_" . $board_num . " WHERE board_id=?";
$stmt = $con -> prepare($content_query);
$stmt -> bind_param('i', $ID_NUM);
$stmt -> execute();
$content_result = $stmt -> get_result();
$content = $content_result -> fetch_assoc();
$likes = $content['likes'];
$likers = $content['likers'];
if($likers!=NULL){
$data = json_decode($likers, true); //json 배열을 php배열
if(in_array($_SESSION['id'], $data)){
$i = array_search($_SESSION['id'], $data);
unset($data[$i]);
$data = array_values($data);
$data = json_encode($data);
$like_up = "UPDATE board_". $board_num . " SET likers = '" . $data. "', likes = likes - 1 WHERE board_id=?";
$stmtl = $con -> prepare($like_up);
$stmtl -> bind_param('i', $ID_NUM);
$stmtl -> execute();
}else{
$i = count($data);
$data[$i]=$_SESSION['id'];
$data = array_values($data);
$data = json_encode($data);
$like_up = "UPDATE board_". $board_num . " SET likers = '" . $data. "', likes = likes + 1 WHERE board_id=?";
$stmtl = $con -> prepare($like_up);
$stmtl -> bind_param('i', $ID_NUM);
$stmtl -> execute();
}
}elseif($likers===NULL){
$data=[$_SESSION['id']];
$data = json_encode($data);
$like_up = "UPDATE board_". $board_num . " SET likers = JSON_ARRAY(" .$_SESSION['id'] . "), likes = likes + 1 WHERE board_id=?";
$stmtl = $con -> prepare($like_up);
$stmtl -> bind_param('i', $ID_NUM);
$stmtl -> execute();
}
?>
이제 이 페이지에 요청을 보낼 클릭할 버튼을 만들도록 하겠다.
하트모양을 가져와서 버튼을 눌렀을경우 색이 바뀌게끔 꾸며주었다.
이는 JS함수로 .like-button i라는 DOM요소가 토글되는 함수를 짜주었고 이 DOM요소가 토글되어있을경우 색이 바뀌고 토글이 풀릴 경우 색이 다시 검은색으로 돌아온다.
추가적으로 만약 로그인이 안되어있을 경우에 이 버튼을 누른다면 아무일도 일어나지 않지만 사용자의 편의성을 위해 alert창으로 로그인이 필요하다는 창을 띄워주었다.
버튼을 누를경우에 DB에 조회수를 나타내는 수를 추가하는 페이지로 요청을 보내야 하는데 action을 통한 전송은 페이지가 이동하기에 페이지를 여러번 로딩한다는 단점이 있다. 이를 줄이기 위해서 페이지를 옮기지 않도록 fetch를 통해서 요청을 전송하였다. 물론 method나 응답값이 필요없기에 한줄로 코드를 짰다.
하지만 여기서 여러 문제점이 발생하였다.
첫 번째로는 바로 이미 눌렀다가 다시 페이지를 로드하게되면 추천은 되어있지만 토글은 되어있지 않아 눌렀는지 모르게 되어버렸다. 이를 해결하기 위해서 DB에서 이 게시글에 추천을 눌렀는지 확인을 하고 추천이 되어있다면 토글하여 CSS를 바꾸는 함수를 실행시켰다.
두 번쨰로 추천은 눌렀지만 조회수 변경이 일어나지 않는다는것이다. 처음에는 php로 페이지를 작성하여 전송하였기에 새로고침하여 페이지를 다시 로드하지 않는한 추천수가 바뀌지 않았다. 그래서 버튼을 누를경우 자동으로 페이지가 새로고침 되도록 location.reload를 사용하였다. 다만 너무 빠르게 누를경우 서버로의 전송속도와 DB의처리속도등으로 이 값이 업로드가 되지 않았다. 그래서 생각한 방법이 DOM요소를 변경하는 JS코드였다.
조회수가 표시되는 DOM요소를 가져와 그 값을 저장하고 만약 좋아요 버튼 CSS가 변경할 때마다 변수값이 증가하고 그 횟수가 홀수면 +1, 짝수면 -1하도록 하였다.
<html>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<html>
<head>
<style>
#md {
display: flex;
justify-content: center;
}
.like-button {
display: inline-block;
cursor: pointer;
}
.like-button i {
font-size: 24px;
color: #000;
}
.like-button i:hover {
color: red;
}
.like-button i.clicked {
color: #ff0000;
}
</style>
<script>
var elements;
var likes;
var clicknum = 0;
var text
window.onload = function() {
elements = document.getElementsByClassName("likephp");
text = elements[0].textContent;
likes = parseInt(text);
};
function handleLikeClick() {
if (sessionok===0){
alert("로그인이 필요합니다.");
}else{
likestyle();
submitlike();
}
}
function likestyle() {
var icon = document.querySelector('.like-button i');
icon.classList.toggle('clicked');
clicknum++;
}
function submitlike() {
fetch('../likes.php/?id=<?php echo $ID_NUM ?>');
// 텍스트를 숫자로 변환
if (clicknum % 2 === 0) {
elements[0].textContent = likes - 1;
elements[1].textContent = likes - 1;
likes--;
} else {
elements[0].textContent = likes + 1;
elements[1].textContent = likes + 1;
likes++;
}
// location.reload();
}
</script>
</head>
<body>
<div id="md" class="like-button">
<i class="far fa-heart" onclick="handleLikeClick()"></i>
</div>
</body>
</html>
<?php
require_once '../tool/session_open.php';
require_once '../tool/db_conn.php';
// require_once '../tool/chack_er.php';
if(!$_SESSION['loggedin']){
echo "<script> var sessionok = 0;</script>";
}else{
echo "<script> var sessionok = 1;</script>";
}
$ID_NUM = $_GET["id"];
$content_query = "SELECT * FROM board_" . $board_num . " WHERE board_id=?";
$stmt = $con -> prepare($content_query);
$stmt -> bind_param('i', $ID_NUM);
$stmt -> execute();
$content_result = $stmt -> get_result();
$content = $content_result -> fetch_assoc();
$likes = $content['likes'];
$likers = $content['likers'];
if($likers!=NULL){
$data = json_decode($likers, true); //json 배열을 php배열
if(in_array($_SESSION['id'], $data)){
echo "<script>likestyle();</script>";
}
}
?>
'프로그래밍 및 코딩 > PHP' 카테고리의 다른 글
게시판 만들기 _ 정렬기능 및 날짜검색기능 (0) | 2023.06.19 |
---|---|
게시판 만들기_조회수 기능 (0) | 2023.06.19 |
CLOB / BLOB (0) | 2023.06.14 |
DB에 파일 업로드 및 다운로드 (CLOB/BLOB) (0) | 2023.06.14 |
서버시간 가져오기 (0) | 2023.06.14 |