본문 바로가기

개발과제

[노말틱 모의 해킹 취업반 8주차 개발과제 ] 게시판 만들기(4) - 조회수 기능

안녕하세요! 어제는 파일 다운로드를 만들었습니다!

 

이번에는 조회수 기능을 만들어서 넣겠습니다.

 

오늘은 간단하게 끝날 것 같아요!

.

.

.

.

우선 게시물 데이터베이스에 조회수를 담을 수 있는 칼럼을 만들겠습니다

 

 

이렇게 했습니다

 

이제 board.php로 넘어 가겠습니다.

출력할 때 views도 출력하게 하겠습니다!

sql문 먼저 손 보겠습니다. 가져올 때 id,title,detail이랑 views도 가져오게요

 

            //작성된 게시물들 조회 문
            $sql = "SELECT board_id,id,title,views FROM $db_board";

 

그리고 출력되게 하겠습니다

 

            if(mysqli_num_rows($result) > 0) {
                //게시물 출력
                while($row = mysqli_fetch_assoc($result)) {
                    $index = $row['board_id'];
                    $id = $row['id'];
                    $title = $row['title'];
                    echo '<p><a href="view_board.php?index='.$index.'">'.$title.'</a> : '.$id.'작성함 조회수: '.$row['views'].'</p>';
                }
            } else {
                echo "게시물이 없습니다!";
            }

 

이러면 되겠죠

 

한 번 확인하겠습니다

 

 

잘 나오네요!

 

이제 게시물을 확인할 때 조회수가 1 증가하게 만들겠습니다!

view_board.php에서 코드 손 보면 되겠네요!

 

            //GET방식으로 전달된 index 받는다
            $board_id = mysqli_real_escape_string($conn,$_GET['index']);

            //조회수 증가하는 sql문
            $sql_view = "UPDATE $db_board SET views = views + 1 WHERE board_id = '$board_id'";
            //실행
            $result_view = mysqli_query($conn, $sql_view);

저기 get방식으로 받을 때 escape로 행여나 sql 공격을 방지하는 코드 추가했습니다

 

그리고 UPDATE이용해서 1을 더하게 했습니다

 

그리고 맨 위에다가 조회수가 몇인지 보이게 하겠습니다!

 

            //게시물 출력
            while($row = mysqli_fetch_assoc($result)) {
                echo '<p>조회수: '.$row['views'].'</p>';
                echo '<p>ID: '.$row['id'].'</p>';
                echo '<p>Title: '.$row['title'].'</p>';
                echo '<p>Detail: '.$row['detail'].'</p>';
                echo '<p>Date: '.$row['date'].'</p>';
                if (isset($row['file_name'])) {
                    $file_name = explode('_', $row['file_name'])[1]; // '_' 문자를 기준으로 분리 후 첫번째 요소(파일명)만 가져옵니다.
                    $download_url = 'download_process.php?filename='.$row['file_name'];
                    echo '<p>FILE: <a href="'.$download_url.'">'.$file_name.'</a></p>';
                }
                
                //로그인한 사용자의 정보 가져온다
                $user_id = $_SESSION['login_id'];

                //게시물 작성자와 로그인한 ID와 일치한 경우
                if($row['id'] == $user_id) {
                    //게시물 수정 버튼을 보여준다
                    echo "<form method='POST' action='fix_board.php'>
                            <input type='hidden' name='board_id' value='".$row['board_id']."'>
                            <p><button type='submit'>게시물 수정</button></p>
                          </form>";

                    //게시물 삭제 버튼을 보여준다
                    echo "<form method='POST' action='delete_board.php'>
                            <input type='hidden' name='board_id' value='".$row['board_id']."'>
                            <p><button type='submit'>삭제</button></p>
                          </form>";
                }
            }

 

 

이렇게요 한 번 실행해보겠습니다

 

제가 봐서 증가 된걸 확인 했습니다!

 

근데 문제점이 있습니다

 

조회수 복사가 가능합니다

 

새로고침을 하면 계속 조회수가 올라가집니다! 그러니 저는 한 세션이 일정 시간 동안 조회수가 안 올라가지게 하겠습니다!

 

일단 저는 마지막으로 본 시간을 세션에 저장하게 하겠습니다. 그리고 현재 시간과 차이가 60분 차이 나면 그때 조회수

올라가게 하겠습니다!

 

            // 세션에 마지막 조회 시간 정보가 있는지 확인
            if (!isset($_SESSION['last_view_time'])) {
                // 세션에 마지막 조회 시간 정보가 없으면 현재 시간을 저장
                $_SESSION['last_view_time'] = time();
            } else {
                // 세션에 마지막 조회 시간 정보가 있으면 일정 시간이 지났는지 확인
                $last_view_time = $_SESSION['last_view_time'];
                $current_time = time();
                $time_diff = $current_time - $last_view_time;
                if ($time_diff >= 3600) { // 36600초(1시간) 이상 지났으면 조회수 증가
                //조회수 증가하는 sql문
                $sql_view = "UPDATE $db_board SET views = views + 1 WHERE board_id = '$board_id'";
                //실행
                $result_view = mysqli_query($conn, $sql_view);

                // 세션에 현재 조회 시간을 저장
                $_SESSION['last_view_time'] = $current_time;
                }
            }

 

세션 last view_time에 저장되어 있는지 확인해서 없으면 현재 시간을 저장하고

 

current_time에는 현재 시간을 저장해서

time_diff에 서로 뺀 시간을 저장하게 됩니다! 이는 초단위로 계산이 됩니다

그래서 1시간이면 3600초 적으면 되겠죠

 

근데 지금 개발 중인데 1시간을 기다릴 시간 없습니다 잠깐 10초으로 설정하고 하겠습니다

 

if ($time_diff >= 10) { // 36600초(1시간) 이상 지났으면 조회수 증가

 

잠깐 이러고 실행해보겠습니다!

 

A few time later..

 

됬네요!

 

 

 

 

근데 문제점이 있네요 세션이 다 같이 할당해서 다른 게시물이 안 올라가집니다!

 

분명 봤는데 안 올라가네요

 

그러니 코드를 조금 수정하겠습니다

 

            //가독성 위해 다른 변수에 저장
            $last_viewed_time_for_board_id = 'last_view_time_'.$board_id;

            // 세션에 마지막 조회 시간 정보가 있는지 확인
            if (!isset($_SESSION[$last_viewed_time_for_board_id])) {
                // 세션에 마지막 조회 시간 정보가 없으면 현재 시간을 저장
                $_SESSION[$last_viewed_time_for_board_id] = time();
            } else {
                // 세션에 마지막 조회 시간 정보가 있으면 일정 시간이 지났는지 확인
                $last_view_time = $_SESSION[$last_viewed_time_for_board_id];
                $current_time = time();
                $time_diff = $current_time - $last_view_time;
                if ($time_diff >= 10) { // 36600초(1시간) 이상 지났으면 조회수 증가
                //조회수 증가하는 sql문
                $sql_view = "UPDATE $db_board SET views = views + 1 WHERE board_id = '$board_id'";
                //실행
                $result_view = mysqli_query($conn, $sql_view);

                // 세션에 현재 조회 시간을 저장
                $_SESSION[$last_viewed_time_for_board_id] = $current_time;
                }
            }

변수명이 좀 길지만 가독성을 위해서 이렇게 했습니다.

 

다시 해보겠습니다

 

조회수 4인데

 

조금만 더 기다리고 새로고침 하면??

 

 

쨘 잘 나오네요!

 

이제 10초 간격을 늘려서 1시간으로 바꾸겠습니다

 

이렇게요

 

오늘은 이렇게 조회수 기능을 만들어 봤습니다!

다음에는 좋아요도 넣어보겠습니다!

 

감사합니다

 

.

.

.

.

.

 

-view_board.php

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>게시물 보는중</title>
    </head>
    <body>
        <p>
        <?php 
            include 'DB_INFO.php'; //데이터 베이스 정보

            //데이터베이스 연결
            $conn = mysqli_connect($host,$username,$password,$db_board);

            //데이터베이스 오류시 종료
            if(mysqli_connect_errno()) {
                die("데이터 베이스 오류: ". mysqli_connect_error());
            }

            session_start(); //세션 시작

            if(!isset($_SESSION['login_id'])) {
                //로그인하지 않은 사용자
                header("Location: login.php"); //login 화면으로 바꾼다
                exit(); //이 페이지를 바로 닫는다
            }

            //GET방식으로 전달된 index 받는다
            $board_id = mysqli_real_escape_string($conn,$_GET['index']);
            //가독성 위해 다른 변수에 저장
            $last_viewed_time_for_board_id = 'last_view_time_'.$board_id;

            // 세션에 마지막 조회 시간 정보가 있는지 확인
            if (!isset($_SESSION[$last_viewed_time_for_board_id])) {
                // 세션에 마지막 조회 시간 정보가 없으면 현재 시간을 저장
                $_SESSION[$last_viewed_time_for_board_id] = time();
            } else {
                // 세션에 마지막 조회 시간 정보가 있으면 일정 시간이 지났는지 확인
                $last_view_time = $_SESSION[$last_viewed_time_for_board_id];
                $current_time = time();
                $time_diff = $current_time - $last_view_time;
                if ($time_diff >= 3600) { // 36600초(1시간) 이상 지났으면 조회수 증가
                //조회수 증가하는 sql문
                $sql_view = "UPDATE $db_board SET views = views + 1 WHERE board_id = '$board_id'";
                //실행
                $result_view = mysqli_query($conn, $sql_view);

                // 세션에 현재 조회 시간을 저장
                $_SESSION[$last_viewed_time_for_board_id] = $current_time;
                }
            }

            //작성된 게시물들 조회 문
            $sql = "SELECT * FROM $db_board WHERE board_id = '$board_id' ";
            //쿼리문 실행
            $result = mysqli_query($conn, $sql);
            
            //게시물 출력
            while($row = mysqli_fetch_assoc($result)) {
                echo '<p>조회수: '.$row['views'].'</p>';
                echo '<p>ID: '.$row['id'].'</p>';
                echo '<p>Title: '.$row['title'].'</p>';
                echo '<p>Detail: '.$row['detail'].'</p>';
                echo '<p>Date: '.$row['date'].'</p>';
                if (isset($row['file_name'])) {
                    $file_name = explode('_', $row['file_name'])[1]; // '_' 문자를 기준으로 분리 후 첫번째 요소(파일명)만 가져옵니다.
                    $download_url = 'download_process.php?filename='.$row['file_name'];
                    echo '<p>FILE: <a href="'.$download_url.'">'.$file_name.'</a></p>';
                }
                
                //로그인한 사용자의 정보 가져온다
                $user_id = $_SESSION['login_id'];

                //게시물 작성자와 로그인한 ID와 일치한 경우
                if($row['id'] == $user_id) {
                    //게시물 수정 버튼을 보여준다
                    echo "<form method='POST' action='fix_board.php'>
                            <input type='hidden' name='board_id' value='".$row['board_id']."'>
                            <p><button type='submit'>게시물 수정</button></p>
                          </form>";

                    //게시물 삭제 버튼을 보여준다
                    echo "<form method='POST' action='delete_board.php'>
                            <input type='hidden' name='board_id' value='".$row['board_id']."'>
                            <p><button type='submit'>삭제</button></p>
                          </form>";
                }
            }
        ?>
        </p>
        <p>
        <?php session_start();
                if (isset($_SESSION['write_error'])) {
                    echo $_SESSION['write_error'];
                    unset($_SESSION['write_error']);
                }
        ?>
        </p>
        <p>
        <?php session_start();
                if (isset($_SESSION['file_error'])) {
                    echo $_SESSION['file_error'];
                    unset($_SESSION['file_error']);
                }
        ?>
        </p>
        <p></p>
        <form action="write_board.php" method="POST"> 
            <p><input type="submit" name="write" value="게시판 작성"></p>
        </form>
        <form action="board.php">
            <p><input type="submit" value="메인페이지로"></p>
        </form>
    </body>
</html>

 

 

-board.php

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Welcome!</title>
    </head>
    <body>
        <h1>MENU</h1>
        <form method ="POST" action="board.php">
            <input type = "text" name="search" placeholder="검색">
            <input type="submit" value="검색">
        </form>
        <p>
        <?php 
            include 'DB_INFO.php'; //데이터 베이스 정보

            //데이터베이스 연결
            $conn = mysqli_connect($host,$username,$password,$db_board);

            //데이터베이스 오류시 종료
            if(mysqli_connect_errno()) {
                die("데이터 베이스 오류: ". mysqli_connect_error());
            }

            session_start(); //세션 시작

            if(!isset($_SESSION['login_id'])) {
                //로그인하지 않은 사용자
                header("Location: login.php"); //login 화면으로 바꾼다
                exit(); //이 페이지를 바로 닫는다
            }

            //한 페이지에 보여줄 게시물 수
            $num_per_page = 5;

            //현재 페이지 번호
            if(isset($_GET['page'])) {
                $page = intval($_GET['page']);
            } else {
                $page = 1;
            }

            //전체 게시물 수 조회
            $total_sql = "SELECT count(*) AS cnt FROM $db_board";
            $total_result = mysqli_query($conn,$total_sql); //sql문 실행
            $total_row = mysqli_fetch_assoc($total_result); //결과를 배열로 가져온다
            $total_posts = $total_row['cnt']; //배열 중 cnt의 값을 가져온다

            //전체 페이지 수
            $total_pages = ceil($total_posts / $num_per_page);

            //각 페이지 시작 인덱스
            $start = ($page - 1) * $num_per_page;

            //작성된 게시물들 조회 문
            $sql = "SELECT board_id,id,title,views FROM $db_board";

            //검색이 입력된 경우
            if(isset($_POST['search']) && !empty($_POST['search'])) {
                $search = mysqli_real_escape_string($conn, $_POST['search']);
                $sql = "SELECT board_id,id,title FROM $db_board WHERE title LIKE '%$search%'";
                $total_sql = "SELECT count(*) AS cnt FROM $db_board WHERE title LIKE '%$search%'";
            }
            
            //sql문에 추가로 작성하고 LIMIT 설정하고 DESC 즉 내림차순으로 정렬
            $sql .= " ORDER BY board_id DESC LIMIT $start, $num_per_page";

            //쿼리문 실행
            $result = mysqli_query($conn, $sql);

            if(mysqli_num_rows($result) > 0) {
                //게시물 출력
                while($row = mysqli_fetch_assoc($result)) {
                    $index = $row['board_id'];
                    $id = $row['id'];
                    $title = $row['title'];
                    echo '<p><a href="view_board.php?index='.$index.'">'.$title.'</a> : '.$id.'작성함 조회수: '.$row['views'].'</p>';
                }
            } else {
                echo "게시물이 없습니다!";
            }
            
            echo '<p> [ ';
            
            // 현재 페이지를 10으로 나눈 몫에 10을 곱한 값에서 1을 빼면
            // 현재 페이지가 몇 번째 페이지 블록에 있는지 알 수 있습니다.
            $block_start = floor(($page-1)/10)*10;

            if ($block_start > 1) {
                // 이전 페이지 블록이 있다면, 다음 버튼을 출력합니다.
                $next_block_start = $block_start - 10;
                if($next_block_start == 0) {
                    $next_block_start += 1; //0페이지는 존재 하지 않기에 1더한다
                }
                echo '<a href="?page=' . $next_block_start .'"><< </a>';
            }

            // 이전 버튼 출력
            if ($page > 1) {
                echo '<a href="?page=' . ($page-1) .'">< </a> ';
            }
            
            // 페이지 링크 출력
            for ($i = $block_start+1; $i <= min($block_start+10, $total_pages); $i++) {
                if($i == $page) {
                    echo '<strong>'.$i.' </strong>';
                } else {
                    echo '<a href="?page=' . $i .'">'.$i. '</a> ';
                }
                echo ' ';
            }

            // 다음 버튼 출력
            if ($page < $total_pages) {
                echo '<a href="?page=' . ($page+1) .'">> </a> ';
            }
            
            if ($block_start+10 < $total_pages) {
                // 다음 페이지 블록이 있다면, 다음 버튼을 출력합니다.
                $next_block_start = $block_start + 11;
                echo '<a href="?page=' . $next_block_start .'">>></a>';
            }

            echo ' ]</p>';
            
        ?>
        </p>
        <p></p>
        <form action="write_board.php" method="POST"> 
            <p><input type="submit" name="write" value="게시판 작성"></p>
        </form>
        <form action="only_login.php"> 
            <p><input type="submit" value="메인페이지로"></p>
        </form>
    </body>
</html>

 

 

 

-4/20 보안 관련해서 코드 조금 더 수정 했습니다!

https://mynameisarke.tistory.com/24

 

[노말틱 모의 해킹 취업반 개발과제 (2)] 보안 관련해서 보완 하기

안녕하세요! 이태까지 제가 만든 웹 사이트에 보안을 좀 더 보완하겠습니다! 오늘은 파일 업로드에 보안을 좀 더 강화하겠습니다 저는 지정한 디렉터리에 저장을 하게 했는데 이는 적절한 보안

mynameisarke.tistory.com