본문 바로가기

Web

[Web] php, mysql을 활용한 게시판 글 수정 및 좋아요 구현 / 웹개발-8

 

글 수정을 위해선 작성된 글을 볼 수 있어야 한다. 제목란에 하이퍼링크를 걸어 작성된 글을 DB에서 가져와 화면에 뿌려주는 파일을 작성했다.

 

각 글의 제목을 클릭하면 이동할 수 있다.

 

read.php


<?php
include "/opt/homebrew/var/www/db/db_init.php";
session_start();
$username = $_SESSION["username"];
$idx = $_GET['idx'];

$sql_board = "SELECT * from board WHERE board_id = '$idx'";
$sql_like = "SELECT * FROM like_tb WHERE like_boardidx = '$idx'";

$result_board = $conn->query($sql_board);
$row_board = $result_board->fetch_assoc();

$result_like = $conn->query($sql_like);
$total_likes_count = 0;
while ($row = $result_like->fetch_assoc()) {
    $total_likes_count += $row["like_count"];
}

?>

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf8">
        <title>글 읽기</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
            $("#checkLike").click(function(){
                var idx =  '<?php echo $idx; ?>';
                var like_count;
                $.ajax({
                    async: true,
                    type: 'POST',
                    data: {'idx': idx},
                    url: '/board/like.php',
                    dataType: 'text',
                    success: function(data){
                        document.getElementById("likeCount").innerText = data;
                    },
                    error: function(error){
                        alert('error: ' + error);
                    }
                });

        });
        });
        </script>
        <style>
            button {
                font-size:13px;
            }
        </style>
    </head>
    <body>
        <table>
            <tr>
                <td>제목: <?php echo $row_board["title"] ?></td>
            </tr>
            <tr>
                <td>작성자: <?php echo $row_board["writer"] ?></td>
            </tr>
            <tr>
                <td>내용: <?php echo $row_board["content"] ?></td>
            </tr>

        </table>
        <form action="/board/modify.php" style="display: inline;" method="get">
            <input type="hidden" name="idx" value="<?php echo $idx ?>">
            <button type="submit">수정하기</button>
        </form>
        <form action="/board/delete.php" style="display: inline;" method="get">
            <input type="hidden" name="idx" value="<?php echo $idx ?>">
            <button type="submit">삭제하기</button>
        </form>
        <button id="checkLike"><img src="/images/thumbs-up-regular.svg" alt="좋아요" width="35" height="15">
            <span id="likeCount"><?php echo $total_likes_count ?></span>
        </button>
    </body>

 

 

👆 위와같이 세개의 버튼과 함께 작성된 글이 나오고 있다.

 

GET 요청 시 쿼리스트링에 idx값을 넘겨 받아 클릭한 글을 출력하였다.

 

수정하기 버튼을 누르면 modify.php에 GET 요청을 보내게 된다. 이때 인덱스도 넘겨주어야 하기 때문에 hidden 속성을 이용했다.

 

 

hidden 속성의 경우 사용자 UI에서는 보이지 않으나 개발자 도구를 통해 코드에서 확인이 가능하다. HTTP 요청 시 form 내부에 적으면 같이 전송이 된다. 인덱스를 굳이 화면에 표시하기엔 지저분 할때 hidden 속성을 사용하면 편리하다.

 

modify.php

modify.php는 수정할 수 있는 폼 형태로 바뀌며, 수정 후의 로직을 처리한다. 마찬가지로 인덱스를 통해 원하는 글을 수정할 수 있게 된다.

 

수정하기 버튼을 누르면 편집이 가능하도록 바뀐다. 저장하기 버튼을 누르면 편집한 내용을 토대로 DB에 쿼리문이 날라가게 된다. 취소 버튼을 누르면 이전 페이지로 돌아가게 된다.

 

<form action="/board/modify_ok.php" style="display: inline;" method="post">
        <table>
            <tr>
                <td>제목: <textarea name="title" id="title" rows="1" cols="55" placeholder="제목" maxlength="100" required><?php echo $row["title"] ?></textarea></td>
            </tr>
            <tr>
                <td>작성자: <?php echo $row["writer"] ?></td>
            </tr>
            <tr>
                <td>내용: <textarea name="content" id="content" rows="1" cols="55" placeholder="제목" maxlength="100" required><?php echo $row["content"] ?></textarea></td>
                <input type="hidden" name="idx" value="<?php echo $idx ?>">
            </tr>

        </table>
            <button type="submit">저장하기</button>
    </form>

 

저장하기 버튼을 누르게 되면 modify_ok에 데이터를 넘긴다. 실질적으로 데이터를 처리하는 코드는 modify_ok.php에 존재하게 된다.

 

 

		<script>
            function goBack(){
                location.href="/board/read.php?idx=<?php echo $row["board_id"] ?>";
            }
        </script>

 

취소 버튼이 눌렸을 때 동작하는 코드이다. 간단하게 이전 페이지로 돌아간다. 

 

modify_ok.php

<?php
include "/opt/homebrew/var/www/db/db_init.php";

session_start();
$title = $_POST["title"];
$content = $_POST["content"];
$idx = $_POST["idx"];

$sql = "UPDATE board SET title='$title', content='$content' WHERE board_id = '$idx'";

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

if ($result) {
    echo "<script>alert('수정되었습니다.'); location.href='/login/login_success.php'</script>";
} else {
    echo "<script>alert('수정에 실패했습니다.')</script>";
}

 

update 쿼리문을 통해 DB에 저장된 글 정보를 수정한다. 수정 후 리다이렉션 된다.

 

다음은 좋아요 기능이다. 버튼을 누르면 페이지 리로드 없이 좋아요 숫자가 올라가야 하기 때문에 비동기식 Ajax 통신이 필요하다.

 

 

버튼 부분이다. total_likes_count라는 변수를 echo해주고 있다. 또한 span태그로 감싸져 있으며 span 태그의 id는 likeCount이다.

 

 

like.php에 POST요청을 보내는 로직이며 이를 비동기식으로 처리하는 코드이다. 요청 데이터로는 글의 인덱스 $idx 변수만이 전송 된다. 전송이 성공했을 경우 id가 likeCount인 태그에 like_count를 추가한다. likeCount는 span태그의 id이다.

 

like.php

<?php
include "/opt/homebrew/var/www/db/db_init.php";
session_start();

$username = $_SESSION["username"];
$idx = $_POST["idx"];

$check_sql = "SELECT * FROM like_tb WHERE (like_username = '$username' and like_boardidx = '$idx')";
$check_result = $conn->query($check_sql);
$row = $check_result->fetch_assoc();
if ($check_result) {
    if ($check_result->num_rows >= 1) {
        if ($row["like_count"] >= 1) {
            $sql = "UPDATE like_tb SET like_count = like_count - 1 WHERE like_boardidx = '$idx' and like_username = '$username'";
            $result = $conn->query($sql);
        } else {
            $sql = "UPDATE like_tb SET like_count = like_count + 1 WHERE like_boardidx = '$idx' and like_username = '$username'";
            $result = $conn->query($sql);
        }
    } else {
        $sql = "INSERT INTO like_tb (like_username, like_boardidx) VALUES ('$username', '$idx')";
        $result = $conn->query($sql);
        $sql = "UPDATE like_tb SET like_count = like_count + 1 WHERE like_boardidx = '$idx' and like_username = '$username'";
        $result = $conn->query($sql);
    }

    $sql_like_count = "SELECT * FROM like_tb WHERE like_boardidx = '$idx'";
    $total = 0;
    $result_like_count = $conn->query($sql_like_count);
    while ($row = $result_like_count->fetch_assoc()) {
        $total += $row["like_count"];
    }
    echo $total;

} else {
    echo "Error checking like: " . $conn->error;
}

 

실질적으로 ajax 통신이 이루어지는 코드이다. 우선 좋아요 기능을 위한 DB 구조는 아래와 같다. 

 

like_idx는 기본키로서 지정을 해주었으며 실제 쓰이는 컬럼으론 like_username(좋아요 누른 사용자), like_boardidx(좋아요 눌린 게시 글 번호), like_count(좋아요 눌린 여부, 0이면 안 눌림, 1이면 눌림 해당 값을 전부 더 하여 총 좋아요 갯수를 표시함)

 

이제 코드 설명으로 돌아가자.

 

먼저 다음과 같은 쿼리문을 날린다.

 

 

이 쿼리문은 세션 정보에서 가져온 username과 현재 보고 있는 게시글의 인덱스를 가져와 쿼리문을 날리게 된다. 좋아요를 누른 사용자와 눌린 게시글을 추적하기 위함이다. 

 

if ($check_result->num_rows >= 1) {
        if ($row["like_count"] >= 1) {
            $sql = "UPDATE like_tb SET like_count = like_count - 1 WHERE like_boardidx = '$idx' and like_username = '$username'";
            $result = $conn->query($sql);
        } else {
            $sql = "UPDATE like_tb SET like_count = like_count + 1 WHERE like_boardidx = '$idx' and like_username = '$username'";
            $result = $conn->query($sql);
        }
    }

 

첫 번째 if문은 위 쿼리문의 결과에서 반환된 행이 한개 이상인지 판단한다. 한 개 이상이라면 이미 해당 사용자를 추적하고 있는 상태이기 때문에 DB에 추적을 위한 쿼리를 날릴 필요가 없어진다. 바로 like_count가 1개 이상인지 확인한다.

 

like_count가 1이상이면 이미 누른 상태이기 때문에 좋아요 숫자가 하나 떨어지는 동작을 처리한다. update 쿼리문을 통해 like_count를 하나 줄인다.

 

만약 like_count가 0이라면 안 누른 상태이기 때문에 like_count를 하나 증가시키는 쿼리를 날린다.

 

else {
        $sql = "INSERT INTO like_tb (like_username, like_boardidx) VALUES ('$username', '$idx')";
        $result = $conn->query($sql);
        $sql = "UPDATE like_tb SET like_count = like_count + 1 WHERE like_boardidx = '$idx' and like_username = '$username'";
        $result = $conn->query($sql);
    }

 

이번엔 사용자에 대한 추적을 안하고 있는 상태인 경우를 처리한다. 사용자를 추적하기 위해 DB에 세션에서 받아온 username과 게시글의 인덱스 정보(사용자가 어떤 게시글을 보고 있는지)를 가지고 쿼리를 날린다.

 

사용자를 추적하고 있지 않았다면 당연히 좋아요를 누른 적이 없으므로 like_count를 하나 증가시킨다.

 

위 코드는 ajax 통신의 반환값으로 콜백함수를 처리하는 코드이다. 응답받은 data는 

위 코드의 total 변수가 된다. total 변수는 DB의 모든 행들에서 인덱스가 같은 것들만 가져와 like_count를 얻는다. 그렇게 얻은 like_count를 반복문을 돌면서 모두 더하여 반환한다. 

 

이제 ajax 통신에서 응답받은 data는 likeCount의 innerText로 비동기적으로 값이 바뀌게 된다.

 

 


정보

 

1. php에 쿼리문을 날려 행을 반환받고 행이 2개이상일 경우 반복문을 돌면서 행에 접근할 수 있다.

 

2. 쿼리 결과에 ->fetch_assoc()로 접근하면 컬럼의 정보에 접근이 가능하다.

 

3. 안 되는 데에는 이유가 있다.. 코드를 꼼꼼히 보자 ㅠㅠ