PHP/Modern PHP

[PHP] 게시판 만들기 with MVC - 5부 Pagination

DSeung 2023. 12. 27. 17:53

 

이전글 : [PHP] 게시판 만들기 with MVC - 1부 Migration

이전글 : [PHP] 게시판 만들기 with MVC - 2부 Routing

이전글 : [PHP] 게시판 만들기 with MVC - 3부 View(List & Create)

이전글 : [PHP] 게시판 만들기 with MVC - 4부 Controller

 

Pagination

기존에 있던 index.php에서 테이블 부분부터 수정하여 Pagination을 구현합시다.

bbs/view/index.php

    <!-- 게시물 목록 테이블 -->
    <table class="table table-bordered">
        <thead>
        <tr class="text-center">
            <th width="80">번호</th>
            <th width="300">제목</th>
            <th width="100">글쓴이</th>
            <th width="80">추천수</th>
            <th width="80">조회수</th>
            <th width="100">작성일</th>
        </tr>
        </thead>
        <tbody>
        <?php
        // 현재 페이지 설정 값
        $currentPage = $_GET['page'] ?? 1;
        $searchWord = $_GET['search'] ?? '';

        // 페이지마다 보여줄 아이템 개수
        $perPage = 10;
        // 페이지의 시작 인덱스 값
        $startIndex = ($currentPage - 1) * $perPage;

        // 전체 게시글 수
        $total = $post->count($searchWord);

        // 전체 페이지 개수
        $totalPage = ceil($total / $perPage);

        // 현재 페이지에서 보여줄 마지막 페이지
        $endPage = $totalPage > $currentPage + 4 ? $currentPage + 4 : $totalPage;
        $endPage = $endPage < 10 && $totalPage > 10 ? 10 : $endPage;

        // 게시글 목록 가져오기
        $posts = $post->getPosts($searchWord, $startIndex, $perPage);

        if ($posts) {
            $bonusIdx = 0;
            foreach ($posts as $postInfo) {
                /// 30 글자 초과시 ... 저리
                $title = $postInfo["title"];
                if (strlen($title) > 30) {
                    // mb_substr: 한글이 깨지지 않도록 해줌
                    $title = str_replace($postInfo["title"], mb_substr($postInfo["title"], 0, 30, "utf-8") . "...", $postInfo["title"]);
                }
                ?>

                <tr>
                    <td><?= $total - ($startIndex + $bonusIdx++) ?></td>
                    <td>
                        <a href="./read?idx=<?= $postInfo['idx'] ?>">
                            <?= $title . " [" . $postInfo['reply_count'] . "]"; ?>
                            <?php if ($postInfo['is_new']) { ?>
                                <span class="badge badge-primary">new</span>
                            <?php } ?>
                        </a>
                    </td>
                    <td><?= $postInfo['name'] ?></td>
                    <td><?= $postInfo['thumbs_up'] ?></td>
                    <td><?= $postInfo['views'] ?></td>
                    <td><?= $postInfo['created_at'] ?></td>
                </tr>
                <?php
            }
        } else {
            echo "<tr><td colspan='6' class='text-center'>게시글이 없습니다.</td></tr>";
        }
        ?>
        </tbody>
    </table>

    <!-- 페이지네이션 -->
    <nav aria-label="Page navigation">
        <ul class="pagination">
            <li class="page-item">
                <a class="page-link" data-page="1" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
            </li>
            <?php
            for ($page = max($currentPage - 4, 1); $page <= $endPage; $page++) {
                $isActive = $page == $currentPage ? 'active' : '';
                echo "<li class='page-item $isActive'><span class='page-link' data-page='$page'>$page</span></li>";
            }
            ?>
            <li class="page-item">
                <a class="page-link" data-page="<?= $totalPage ?>" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>
        </ul>
    </nav>
</div>
</body>
<script src="/bbs/assets/script/index.js"></script>
</html>

일단 Post Model의 Count와 index.js가 없으니 에러가 발생합니다.

아래에서 추가해 줍시다.

 

Count

bbs/Model/Post.php

<?php

namespace Model;

use PDO;
use PDOException;

class Post extends BaseModel
{
   ...

    /**
     * Post 목록의 개수
     * @param $search string 검색어
     * @return int|mixed
     */
    public function count(string $search)
    {
        try {
            $query = "SELECT count(idx) FROM posts WHERE title like :search";
            $stmt = $this->conn->prepare($query);
            $stmt->bindValue('search', '%' . ($search ?? '') . '%');
            $stmt->execute();
            return $stmt->fetchColumn();
        } catch (PDOException  $e) {
            error_log($e->getMessage());
            return 0;
        }
    }
}

 

Script

bbs/assets/script/index.js

$(document).ready(function () {
    // 페이지 이동
    $(".page-link").click(function () {
        let currentUrl = window.location.href;
        let urlSearchParams = new URLSearchParams(window.location.search);

        // page 파라미터 세팅
        urlSearchParams.set('page', $(this).attr('data-page'));
        location.href = currentUrl.split('?')[0] + '?' + urlSearchParams.toString();
    })
});

 

이제 페이지네이션 기능을 전부 추가했습니다.

데이터를 여러 개 추가하면 아래처럼 페이지네이션 기능을 사용할 수 있고

데이터 추가가 번거롭다면 index.php의 $perPage 값을 줄이면 편하게 체크할 수 있습니다.

 

$perPage = 3을 했을 때에 결과물입니다.

 

반응형