jineecode
php로 게시판 구체적으로 구현하기 (1) 본문
먼저 저는 php를 전문적으로 공부하지 않았으며 문제 해결 기록용으로 남깁니다.
지금까지 구현해왔던 게시판은 키 값이 글 번호였으며 이러한 로직은 게시판의 게시물이 삭제되었을 때 문제가 발생한다. (1번, 2번, 3번의 게시물이 있었을 때, 2번을 삭제하면 1번, 3번만 존재하는 문제)
글 번호가 거슬린다고 하여 매번 테이블을 비우기도 부담스럽고 매번 수정 삭제하기도 거슬린다.
DB로 가서 억지로 글번호를 수정한다고 해도 글을 하나 더 등록하면 키 값이 글 번호이기 때문에 무색해진다.
이 문제를 해결하고 싶어서 몇 개월 골머리를 앓았는데 페이징 작업을 하다가 같이 해결해서 작성한다.
SQL문 코드가 정리가 안 되었음//
1. 공지사항 게시판이다.
해당 페이지 주소는 다음과 같다.
/openconcert/page/notice/notice.php?page=1
?page=1
절대 경로 주소 뒤에 ?page=1이라는 값을 붙혀준다.
별다른 설정을 안 했다면 ?page=1을 붙혀도 같은 화면을 보여줄 것이다.
이것은 GET값을 위한 사전 작업이다.
추후에 적겠지만 이는 현재 페이지가 1페이지라는 것을 나타낸다.
2.
/page/notice/noti_page.php
글 번호와 페이징에 들어갈 초깃값 세팅을 한다.
<?php
$page = isset($_GET['page']) ? $_GET['page'] : 1;
$list_num = 5;
$page_num = 5;
$offset = $list_num*($page-1);
//전체 글 수
include $_SERVER['DOCUMENT_ROOT'].'/openconcert/process/connect/db_connect.php';
$query = "SELECT * FROM opc_noti";
$data = mysqli_query($dbConn, $query);
$total_no = mysqli_num_rows($data);
//전체 페이지 수와 현재 글 번호를 구합니다.
$total_page=ceil($total_no/$list_num);
// 전체글수를 페이지당글수로 나눈 값의 올림 값을 구합니다.
$cur_num=$total_no - $list_num*($page-1);
// 여기부터 페이지
//먼저, 한 화면에 보이는 블록($page_num 기본값 이상일 때 블록으로 나뉘어짐 )
$total_block=ceil($total_page/$page_num);
// 1블록 = 5개의 페이지 / 10개의 페이징 넘버
$block=ceil($page/$page_num); //현재 블록
// 1블록 = 2페이지 / 10개의 페이징 넘버
$first=($block-1)*$page_num;
// 페이지 블록이 시작하는 첫 페이지
$last=$block*$page_num;
//페이지 블록의 끝 페이지
if($block >= $total_block) {
$last=$total_page;
}
?>
코드를 차근차근 확인해보자.
$page = isset($_GET['page']) ? $_GET['page'] : 1;
삼항 연산자.
URL로 넘어온 $_GET['page'] 값이 존재하면 $page의 값은 URL로 넘어온 page 값,
존재하지 않는다면 $page=1이다.
즉, 주소?page=2 이면 $page=2 이고, ?page가 없다면 1이라고 $page는 값을 1로 인식합니다.
$list_num = 5;
한 페이지에 보여줄 목록 갯수 (data)
5개의 목록이 출력됩니다.
$list_num = 4; 라면?
4개만 출력됩니다.
$page_num = 5;
한 화면에 보여줄 페이지 링크(묶음) 갯수 (paging num count)
$page_num = 4;라면?
글번호가 4개만 출력됩니다.
$offset = $list_num*($page-1);
한 페이지의 시작 글 번호 (list num 수만큼 나누었을 때 시작하는 글의 번호)
1페이지에 있을 때
0 = 5 * ( 1 - 1)
2페이지에 있을 때
5 = 5 * ( 2 - 1)
offset은 sql문에서 쓸 예정입니다.
테이블에 있는 전체 데이터의 갯수를 셉니다.
//전체 데이터 수
include $_SERVER['DOCUMENT_ROOT'].'/openconcert/process/connect/db_connect.php';
$query = "SELECT * FROM opc_noti";
$data = mysqli_query($dbConn, $query);
$total_no = mysqli_num_rows($data);
이제 전체 페이지 수와 현재 글 번호를 구합니다.
전체 페이지 수란, 1페이지 당 5개의 글이 있으며
만약 15개의 글($total_no)이 있다면 5개의 글($list_num)씩 나누어 토탈 3페이지($total_page)가 있을 것입니다.
현재 글 번호는 글 하나(데이터)를 삭제하더라도 글 번호의 건너 뜀 없이 번호 순서를 유지할 수 있게 해줍니다.
$total_page=ceil($total_no/$list_num);
// 전체글수를 페이지당글수로 나눈 값의 올림 값을 구합니다.
$cur_num=$total_no - $list_num*($page-1);
//현재 글번호, ex) 20번 = 25개의 글 - 5*(2페이지-1)
여기부터 페이징 작업입니다.
먼저, 전체 블록의 값을 구합니다.
블록이란,
이것을 한 블록이라고 부릅니다.
$page_num 기본값 이상일 때 블록으로 나뉘어집니다.
$total_block=ceil($total_page/$page_num);
1블록 = 5개의 페이지 / 5개의 페이징 넘버
2블록 = 6개의 페이지 / 5개의 페이징 넘버
(페이지가 6개가 되면 이런 식으로 블록이 하나 더 생깁니다)
현재 블록입니다.
$block=ceil($page/$page_num); //현재 블록
1 블록 =1페이지 / 5개의 페이징
$first=($block-1)*$page_num;
// 페이지 블록이 시작하는 첫 페이지
// 0 = (1블록 - 1) * 10
$last=$block*$page_num;
//페이지 블록의 끝 페이지
// 10 = 1블록 * 10페이지
if($block >= $total_block) {
$last=$total_page;
}
페이지 블록이 시작하는 첫 페이지와 끝 페이지, 그리고 블록이 토탈블록보다 크거나 같을 때 마지막 페이지가 토탈페이지와 같은 값을 같도록 하는 조건문입니다.
/page/notice/notice.php
<?php include $_SERVER["DOCUMENT_ROOT"]."/openconcert/page/notice/noti_page.php" ?>
위에서 작성한 초깃값 문서를 인크루드 시켜놓고 작업합니다.
<ul class="noti__lists">
<li class="noti__title">
<span class="noti-num">번호</span>
<span class="noti-id">아이디</span>
<span class="noti-tit">제목</span>
<span class="noti-reg">등록일</span>
<span class="noti-hit">조회수</span>
</li>
<?php
include $_SERVER['DOCUMENT_ROOT'].'/openconcert/process/connect/db_connect.php';
$sql="select * from opc_noti order by OPC_NOTI_num desc limit $offset, $list_num";
$noti_result=mysqli_query($dbConn, $sql);
while($noti_row=mysqli_fetch_array($noti_result)){
$noti_res_num=$noti_row['OPC_NOTI_num'];
$noti_res_tit=$noti_row['OPC_NOTI_tit'];
$noti_res_reg=$noti_row['OPC_NOTI_reg'];
$noti_res_hit=$noti_row['OPC_NOTI_hit'];
?>
<li class="noti__title">
<span class="noti-num"><?=$cur_num?></span>
<span class="noti-id">ADMIN</span>
<span class="noti-tit"><a href="/openconcert/page/notice/noti_view.php?num=<?=$noti_res_num?>" class="noti-link"><?=$noti_res_tit?></a></span>
<span class="noti-reg"><?=$noti_res_reg?></span>
<span class="noti-hit"><?=$noti_res_hit?></span>
</li>
<?php
$cur_num --;}
?>
</ul>
뼈대를 잡고 html과 php를 잘 구분해서 삽입합니다.
<?php
...
$sql="select * from opc_noti order by OPC_NOTI_num desc limit $offset, $list_num";
...
?>
SELECT문
opc_noti로부터 역순으로 $offset부터 $list_num까지 불러옵니다.
$noti_result=mysqli_query($dbConn, $sql);
while($noti_row=mysqli_fetch_array($noti_result)){
$noti_res_num=$noti_row['OPC_NOTI_num'];
$noti_res_tit=$noti_row['OPC_NOTI_tit'];
$noti_res_reg=$noti_row['OPC_NOTI_reg'];
$noti_res_hit=$noti_row['OPC_NOTI_hit'];
...
쿼리를 날려주고 while문으로 반복문을 적어주어 fetch_array 합니다.
while 문의 중괄호는 반복문이 끝날 때 유의하여 닫아줍니다.
<li class="noti__title">
<span class="noti-num"><?=$cur_num?></span>
<span class="noti-id">ADMIN</span>
<span class="noti-tit"><a href="/openconcert/page/notice/noti_view.php?num=<?=$noti_res_num?>" class="noti-link"><?=$noti_res_tit?></a></span>
<span class="noti-reg"><?=$noti_res_reg?></span>
<span class="noti-hit"><?=$noti_res_hit?></span>
</li>
noti-num : 현재 넘버
키 값($noti_res_num)이 아닌 앞서 선언해두었던 현재 넘버($cur_num)임을 주목해주세요.
noti-id: 공지사항이기 때문에 관리자 이름인 ADMIN으로 고정해두었습니다.
noti-tit: a 태그를 연결합니다.
<a href="/openconcert/page/notice/noti_view.php?num=<?=$noti_res_num?>"
class="noti-link">
<?=$noti_res_tit?>
</a>
/noti_view.php
제목을 클릭했을 때 이동되는 상세 게시물 페이지 이름입니다.
링크 뒤의 ?num=<?=$noti_res_num?> 는 게시물을 클릭했을 때 주소를 get으로 넘겨주기 위한 값이며
이때 넘버는 $cur_num이 아닌 $noti_res_num임에 주목해주세요.
noti-reg: 등록 날짜입니다.
noti-hit: 조회수입니다.
<?php
$cur_num --;}
?>
현재 글 넘버의 핵심입니다.
$cur_num --; 을 덧붙혀서 while문을 닫아줍니다.
반복문을 돌며 현재 넘버를 하나씩 빼는 겁니다.
게시물을 역순으로 배치하는데, 현재 글 넘버가 5번이라면 반복문을 돌며 하나씩 숫자가 -1이 되는 로직입니다.
cur_num --; 를 적어주지 않으면 5, 5, 5, 5, 5 이렇게 배치될 것입니다.
페이징 작업입니다.
<!-- pager -->
<div class="pager">
<?php
// 페이징 디자인 //
if($block > 1) {
$prev=$first-1;
?>
<a href='/openconcert/page/notice/notice.php?page=1' id='prev' class="page">
<img src='/openconcert/img/pager-prev-2.png' alt='pager-prev-2'>
</a>
<?php
}
if($page > 1) {
$go_page=$page-1;
?>
<a href='/openconcert/page/notice/notice.php?page=<?=$go_page?>' class="page">
<img src='/openconcert/img/pager-prev-1.png' alt='pager-prev-1'>
</a>
<?php
}
for ($page_link=$first+1;$page_link<=$last;$page_link++) {
if($page_link==$page) {
?>
<a class="page on"><?=$page_link?></a>
<?php
}else {
?>
<a href='/openconcert/page/notice/notice.php?page=<?=$page_link?>' class="page">
<?=$page_link?>
</a>
<?php
}
?>
<?php
}
if ($block < $total_block) {
$next_page=$page+1;
?>
<a href='/openconcert/page/notice/notice.php?page=<?=$next_page?>' class="page">
<img src='/openconcert/img/pager-next-1.png' alt='pager-next-1'>
</a>
<?php
}
if ($last = $total_page) {
?>
<a href='/openconcert/page/notice/notice.php?page=<?=$total_page?>' class="page">
<img src='/openconcert/img/pager-next-2.png' alt='pager-next-2'>
</a>
<?php
}
?>
<!-- page end -->
</div>
HTML과 PHP가 섞여 매우 복잡해보이지만 코드의 흐름을 잃지 않으면 어렵지 않습니다.
조건문은 총 5개입니다.
1. << 맨 처음으로
<?php
// 페이징 디자인 //
if($block > 1) {
$prev=$first-1;
?>
<a href='/openconcert/page/notice/notice.php?page=1' id='prev' class="page">
<img src='/openconcert/img/pager-prev-2.png' alt='pager-prev-2'>
</a>
<?php
}
한 블록이 1보다 클 때, 즉 2블록이 생성되면 << 맨 처음으로 버튼이 생깁니다.
a링크를 누르면 1페이지로 가도록 ?page=1을 넣어주었습니다.
2. < 한 페이지 뒤로
if($page > 1) {
$go_page=$page-1;
?>
<a href='/openconcert/page/notice/notice.php?page=<?=$go_page?>' class="page">
<img src='/openconcert/img/pager-prev-1.png' alt='pager-prev-1'>
</a>
한 페이지가 1보다 클 때, 즉 2페이지가 생기면
$go_page=$page-1; (이전 페이지 변수 = 현재 페이지 - 1)
선언과 함께 < 버튼이 생깁니다.
a링크를 누르면 이전 페이지로 가도록 ?page=<?=$go_page?>을 넣어주었습니다.
3. 페이징 반복문
<?php
}
for ($page_link=$first+1;$page_link<=$last;$page_link++) {
if($page_link==$page) {
?>
<a class="page on"><?=$page_link?></a>
<?php
}else {
?>
<a href='/openconcert/page/notice/notice.php?page=<?=$page_link?>' class="page">
<?=$page_link?>
</a>
<?php
}
?>
<?php
}
1, 2, 3, 4, 5
가 만들어지는 부분입니다.
for 문으로, $page_link가 $first+1부터 (첫페이지+1) 시작하여, $last (맨 마지막 페이지)보다 적거나 같을 때까지 하나씩 늘려가며 반복합니다.
$first 와 $last는 맨 처음에 /page/notice/noti_page.php 에서 따로 선언해주었습니다.
반복문을 시도하면서 조건문을 하나 붙혀줍니다.
if($page_link==$page)
$page_link 가 현재 페이지, $page와 같다면 on 클래스를 넣어 현재 페이지를 붙혀줍니다.
이를 테면 이런 것입니다.
6번이 선택되어 있고, on class가 더 붙혀져 색깔이 입혀졌습니다.
on style은 따로 css로 정해두었습니다.
현재 페이지 외 다른 페이지는 이렇게 else로 마무리 짓습니다.
<?php
}else {
?>
<a href='/openconcert/page/notice/notice.php?page=<?=$page_link?>' class="page">
<?=$page_link?>
</a>
<?php
}
?>
4. > 한 페이지 앞으로
if ($block < $total_block) {
$next_page=$page+1;
?>
<a href='/openconcert/page/notice/notice.php?page=<?=$next_page?>' class="page">
<img src='/openconcert/img/pager-next-1.png' alt='pager-next-1'>
</a>
하나의 블록이 토탈 블록보다 작으면
현재 페이지보다 하나 더 늘어나는 변수 선언과 함께($next_page)
> 버튼이 생깁니다.
a링크를 누르면 다음 페이지로 가도록 <?=$next_page?>을 넣어주었습니다.
5. >> 맨 뒤로
<?php
}
if ($last = $total_page) {
?>
<a href='/openconcert/page/notice/notice.php?page=<?=$total_page?>' class="page">
<img src='/openconcert/img/pager-next-2.png' alt='pager-next-2'>
</a>
<?php
}
?>
마지막 번호와 토탈 페이지 번호가 같으면 맨 뒤로 버튼이 생깁니다.
a 링크를 누르면 토탈 페이지로 넘어갑니다.
위 사이트의 도움을 정말 많이 받았다.
'php' 카테고리의 다른 글
php로 게시판 구체적으로 구현하기 (2) (0) | 2021.04.05 |
---|---|
검색 폼 유형 (0) | 2021.03.31 |
다음 글, 이전 글 php로 구현하기 (0) | 2021.03.30 |
nl2br로 줄바꿈을 한 textarea의 수정? (0) | 2021.03.29 |