반응형

페이징은 좀 어려울 수 있다. 한번에 알아들으면 천재다. 일단 따라해보고 이해가 잘 안되면 넘어가자. 그리고 나중에 자꾸 해보면 된다.

 

페이징은 숫자로 페이지를 넘기는 방식을 해보려고 한다. 리스트에 있는 페이징 부분을 떼어내서 클래스 속으로 집어 넣어보자.

 

/lib/lib.php

<?php include $_SERVER["DOCUMENT_ROOT"]."/inc/dbcon.php";

//글 작성자의 이름을 가져오기 위해 함수를 사용했다. 매개변수인 userid를 통해 이름을 알아낸 후 그 값을 리턴해 준다.
function member_name($userid){
    global $mysqli;//$mysqli 는 dbconn.php에서 만들어진 변수이기때문에 함수안에서 사용하려면 global로 선언해주어야한다.
    $query = "select username from members where userid='".$userid."'";
    $result = $mysqli->query($query) or die("query error => ".$mysqli->error);
    $rs = $result->fetch_object();
    return $rs->username;
}

class Boards {
    private $boardName;//게시판명
    private $boardCount;//게시물수
    private $boardLastDate;//마지막으로 게시물이 등록된 날짜

    public function boardname($multi){
        switch($multi) {
            case "free":$rs="자유게시판";
            break;
            case "humor":$rs="유머게시판";
            break;
            case "star":$rs="연예인게시판";
            break;
        }
        return $rs;
    }

    public function __construct($multi="free"){//생성자다. 생성자에 파라미터가 있다. 파라미터값이 없으면 "free"로 지정한다.
        global $mysqli;
        $query = "select regdate, cnt from board b1
        join (
                select b2.multi, count(*) as cnt from board b2 where status=1 group by b2.multi
        ) board2 on b1.multi=board2.multi
        where b1.multi='".$multi."'
        and status=1 order by bid desc limit 1;";
        $result = $mysqli->query($query) or die("query error => ".$mysqli->error);
        $rs = $result->fetch_object();
        $this->boardName=self::boardname($multi);
        $this->boardCount=$rs->cnt;
        $this->boardLastDate=$rs->regdate;
    }

    public function boardInfo(){
        $bi = array(
            "boardName"=>$this->boardName,
            "boardCount"=>$this->boardCount,
            "boardLastDate"=>$this->boardLastDate
        );
        return $bi;//게시판 정보를 배열로 만들어서 리턴한다.
    }

    public function boardLists($multi="free", $search_keyword = null, $pageNumber = 1, $pageCount = 10){
        global $mysqli;
        $sql = "select b.*, if((now() - regdate)<=86400,1,0) as newid
        ,(select count(*) from memo m where m.status=1 and m.bid=b.bid) as memocnt
        ,(select m.regdate from memo m where m.status=1 and m.bid=b.bid order by m.memoid desc limit 1) as memodate
        ,(select count(*) from file_table f where f.status=1 and f.bid=b.bid) as filecnt
        ,(select filename from file_table_summer fs where fs.status=1 and fs.bid=b.bid order by fs.fid asc limit 1) as thumb
        from board b where multi='".$multi."' ";
        $sql .= " and status=1";
        if(!empty($search_keyword)){
            $search_where = " and (subject like '%".$search_keyword."%' or content like '%".$search_keyword."%')";
        }
        $sql .= $search_where;
        $order = " order by ifnull(parent_id, bid) desc, bid asc";
        if($pageNumber < 1) $pageNumber = 1;
        $startLimit = ($pageNumber-1)*$pageCount;//쿼리의 limit 시작 부분
        $limit = " limit $startLimit, $pageCount";

        $query = $sql.$order.$limit;
        $result = $mysqli->query($query) or die("query error => ".$mysqli->error);
        while($rs = $result->fetch_object()){
            $rsc[]=$rs;
        }
       
        return $rsc;
    }

    public static function totalCount($multi="free", $search_keyword = null){//전체게시물 수 구하기
        global $mysqli;
        $sqlcnt = "select count(*) as cnt from board where multi='".$multi."' ";
        $sqlcnt .= " and status=1";
        if(!empty($search_keyword)){
            $search_where = " and (subject like '%".$search_keyword."%' or content like '%".$search_keyword."%')";
        }
        $sqlcnt .= $search_where;
        $countresult = $mysqli->query($sqlcnt) or die("query error => ".$mysqli->error);
        $rscnt = $countresult->fetch_object();
        $totalCount = $rscnt->cnt;
        return $totalCount;
    }

    public static function paging($multi="free", $search_keyword = null, $pageNumber = 1, $pageCount = 10, $firstPageNumber = 1, $sub_size = 10){
        $totalCount=self::totalCount($multi, $search_keyword);//전체 게시물 수를 구하는 클래스
        $totalPage = ceil($totalCount/$pageCount);//전체 페이지를 구한다.
        $lastPageNumber = $firstPageNumber + $sub_size - 1;//페이징 나오는 부분에서 레인지를 정한다.
        if($lastPageNumber > $totalPage) $lastPageNumber = $totalPage;        

        $paging="
            <nav aria-label=\"Page navigation example\">
                <ul class=\"pagination justify-content-center\">
                    <li class=\"page-item\">
        ";
        $pageNumber1=$firstPageNumber-$sub_size ;
        $paging.="
            <a class=\"page-link\" href=\"".$_SERVER['PHP_SELF']."?pageNumber=".$pageNumber1."&firstPageNumber=".$pageNumber1."&search_keyword=".$search_keyword."&multi=".$multi."\">Previous</a>";
        $paging.="</li>";
        for($i=$firstPageNumber;$i<=$lastPageNumber;$i++){
            $paging.='
                <li class="page-item ';
            if($pageNumber==$i){
                $paging.='active';
            }
            $paging.='
                "><a class="page-link" href="'.$_SERVER['PHP_SELF'].'?pageNumber='.$i.'&firstPageNumber='. $firstPageNumber.'&search_keyword='.$search_keyword.'&multi='.$multi.'">'.$i.'</a></li>
            ';
        }
        $pageNumber2=$firstPageNumber+$sub_size ;
        $paging.='
            <li class="page-item">
                    <a class="page-link" href="'.$_SERVER['PHP_SELF'].'?pageNumber='.$pageNumber2.'&firstPageNumber='.$pageNumber2.'&search_keyword='.$search_keyword.'&multi='.$multi.'">Next</a>
                </li>
            </ul>
            </nav>
        ';

        //error_log ('['.__FILE__.']['.__FUNCTION__.']['.__LINE__.']['.date("YmdHis").']'.print_r($paging,true)."\n", 3, './php_log_'.date("Ymd").'.log');//로그를 남긴다.

        return $paging;

    }

   
}

?>

페이징에서 중요한 것중에 하나가 게시물의 전체 갯수를 구하는 것이다. 그래서 게시물의 전체 갯수를 구하는 함수를 만들었다. 이것도 index.php에 있던 거다. 형식을 잘보고 이렇게 만든다는 것만 알면된다. static이기때문에 인스턴스없이 바로 불러 올 수 가 있다. 같은 클래스 안에서는 self로 불러온다.

 

그 다음이 화면에 페이징 부분을 묘사해주는 페이징 함수다. index.php에 있던 페이징 부분을 php형식으로 바꾸었다. 처음보면 혼돈 그 자체겠지만 찬찬히 따라 해보도록 하자.

 

오류가 나거나 원하는 화면이 나오지 않는 다면 부분 부분 로그를 찍어서 내가 원하는 값이 나오는지 확인해보도록 한다. 그래도 안되면 넘어가자.

 

이제 이렇게 만든 클래스를 이용해서 기존 index.php에서 페이징 부분을 드러내고 새로 만든 클래스를 이용해 화면을 표현해보자.

 

/index.php

<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/header.php";

$search_keyword = $_GET['search_keyword'];

if($search_keyword){
    $search_where = " and (subject like '%".$search_keyword."%' or content like '%".$search_keyword."%')";
}

$pageNumber  = $_GET['pageNumber']??1;//현재 페이지, 없으면 1
if($pageNumber < 1) $pageNumber = 1;
$pageCount  = $_GET['pageCount']??10;//페이지당 몇개씩 보여줄지, 없으면 10
$firstPageNumber  = $_GET['firstPageNumber'];
if($firstPageNumber < 1) $firstPageNumber = 1;

    $multi=$_GET['multi']??"free";//게시판 구분자
    $boards = new Boards($multi);//인스턴스를 생성한다
    $rsc=$boards->boardLists($multi, $search_keyword, $pageNumber, $pageCount);//클래스에 있는 함수를 이용해 게시물 리스트를 가져온다.
//    print_r($rsc);
?>
        <div><?php //클래스 적용부분
            $bi=$boards->boardInfo();
            echo $bi["boardName"]." ( 총 게시물수 : ".$bi["boardCount"]." / 마지막등록일 : ".$bi["boardLastDate"].")";
        ?></div>
        <!-- 더보기 버튼을 클릭하면 다음 페이지를 넘겨주기 위해 현재 페이지에 1을 더한 값을 준비한다. 더보기를 클릭할때마다 1씩 더해준다. -->
        <input type="hidden" name="nextPageNumber" id="nextPageNumber" value="<?php echo $pageNumber+1;?>">
        <table class="table">
        <thead>
            <tr>
            <th scope="col">번호</th>
            <th scope="col">글쓴이</th>
            <th scope="col">썸네일</th>
            <th scope="col">제목</th>
            <th scope="col">등록일</th>
            </tr>
        </thead>
        <tbody id="board_list">
            <?php
                $totalCount = Boards::totalCount($multi,$search_keyword);//전체 게시물 수를 가져오는 클래스
                $idNumber = $totalCount - ($pageNumber-1)*$pageCount;
                foreach($rsc as $r){
                    //검색어만 하이라이트 해준다.
                    $subject = str_replace($search_keyword,"<span style='color:red;'>".$search_keyword."</
                        span>",$r->subject);
                   
            ?>

                <tr>
                    <th scope="row"><?php echo $idNumber--;?></th>
                    <td><?php echo member_name($r->userid);?></td>
                    <td><?php
                        if(!empty($r->thumb)){
                            echo "<img src='/data/".$r->thumb."' width='50'>";
                        }else{
                            echo "null";
                        }
                    ?></td>
                    <td>
                        <?php
                            if($r->parent_id){
                                echo "&nbsp;&nbsp;<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-arrow-return-right\" viewBox=\"0 0 16 16\">
                                <path fill-rule=\"evenodd\" d=\"M1.5 1.5A.5.5 0 0 0 1 2v4.8a2.5 2.5 0 0 0 2.5 2.5h9.793l-3.347 3.346a.5.5 0 0 0 .708.708l4.2-4.2a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 8.3H3.5A1.5 1.5 0 0 1 2 6.8V2a.5.5 0 0 0-.5-.5z\"/>
                              </svg>";
                            }
                        ?>  
                    <a href="/view.php?bid=<?php echo $r->bid;?>"><?php echo $subject?></a>
                    <?php if($r->filecnt){?>
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-card-image" viewBox="0 0 16 16">
                        <path d="M6.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>
                        <path d="M1.5 2A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13zm13 1a.5.5 0 0 1 .5.5v6l-3.775-1.947a.5.5 0 0 0-.577.093l-3.71 3.71-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12v.54A.505.505 0 0 1 1 12.5v-9a.5.5 0 0 1 .5-.5h13z"/>
                        </svg>
                    <?php }?>
                    <?php if($r->memocnt){?>
                        <span <?php if((time()-strtotime($r->memodate))<=86400){ echo "style='color:red;'";}?>>
                            [<?php echo $r->memocnt;?>]
                        </span>
                    <?php }?>
                    <?php if($r->newid){?>
                        <span class="badge bg-danger">New</span>
                    <?php }?>
                </td>
                    <td><?php echo $r->regdate?></td>
                </tr>
            <?php }?>
        </tbody>
        </table>
        <!-- <div class="d-grid gap-2" style="margin:20px;">
            <button class="btn btn-secondary" type="button" id="more_button">더보기</button>
        </div> -->
        <form method="get" action="<?php echo $_SERVER["PHP_SELF"]?>">
        <div class="input-group mb-12" style="margin:auto;width:50%;">
                <input type="text" class="form-control" name="search_keyword" id="search_keyword" placeholder="제목과 내용에서 검색합니다." value="<?php echo $search_keyword;?>" aria-label="Recipient's username" aria-describedby="button-addon2">
                <button class="btn btn-outline-secondary" type="button" id="search">검색</button>
        </div>
        </form>
        <p>
            <?php echo Boards::paging($multi, $search_keyword, $pageNumber, $pageCount, $firstPageNumber);?>
        </p>

        <p style="text-align:right;">

            <?php
                if($_SESSION['UID']){
            ?>
                <a href="write.php"><button type="button" class="btn btn-primary">등록</button><a>
                <a href="/member/logout.php"><button type="button" class="btn btn-primary">로그아웃</button><a>
            <?php
                }else{
            ?>
                <a href="/member/login.php"><button type="button" class="btn btn-primary">로그인</button><a>
                <a href="/member/signup.php"><button type="button" class="btn btn-primary">회원가입</button><a>
            <?php
                }
            ?>
        </p>

<script>
    $("#more_button").click(function () {
       
        var data = {//more_list_page.php에 넘겨주는 파라미터 값이다.
            pageNumber : $('#nextPageNumber').val() ,
            pageCount : <?php echo $pageCount;?>,
            totalCount : <?php echo $totalCount;?>,
            search_keyword : <?php echo $search_keyword;?>
        };
            $.ajax({
                async : false ,
                type : 'post' ,//post방식으로 넘겨준다. ajax는 반드시 post로 해준다.
                url : 'more_list_page.php' ,
                data  : data ,//위에서 만든 파라미터들을 넘겨준다.
                dataType : 'html' ,//리턴받을 형식이다. html말고 text난 json도 있다. json을 가장 많이 쓴다.
                error : function() {} ,
                success : function(return_data) {
                    if(return_data==false){
                        alert('마지막 페이지입니다.');
                        return;
                    }else{
                        $("#board_list").append(return_data);//table 마지막에 붙여준다. 반대는 prepend가 있다.
                        $("#nextPageNumber").val(parseInt($('#nextPageNumber').val())+1);//다음페이지를 위해 1씩 증가해준다.
                    }
                }
        });
    });
</script>

<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/footer.php";

사진처럼 나오면 성공이다. 물론 2,3 페이지를 눌러서 제대로 나오는지도 확인해보자.

 

다음 시간엔 게시물을 등록할때 클래스를 이용해서 등록해보도록 하겠다.

 

반응형

+ Recent posts