안녕하세요!
이번엔 저번에 만든 게시물에서 추가로 기능을 넣겠습니다
바로 페이징 기능입니다!
페이징은 게시물이 너무 많을 때 페이지 별로 나누어서 볼 수 있게 하는 건데요
이걸 한 번 만들어 보겠습니다
.
.
.
.
게시판 페이지인 board.php만 손 보면 되겠네요!
우선적으로 어떡해 코딩할지 생각을 해봅시다.
일단 한 페이지당 얼마나 게시물이 보이게 할지 결정해야 되겠죠?
저는 5개로 하겠습니다
그리고 제 데이터베이스에 몇 개의 게시물이 있는지도 알아야 되겠네요!
그리고.. 총 게시물 개수랑 한 페이지 당 표시되는 개수를 나눠서 페이지가 얼마나 필요한지 알 수 있습니다.
또한 1페이지엔 1번~5번까지 출력 2페이지엔 6~10번까지 출력하게
각 페이지마다 시작 변수를 알 수 있게 코딩을 하면 되겠네요
그리고 보여주게 하는 것은 SQL언어에 LIMIT을 활용하면 되겠습니다..
.
.
.
.
.
.
.
.
한번 코딩을 해보겠습니다.
저는 한 페이지당 5 게시물 보여주게 하기 위해서 따로 변수에 넣겠습니다.
//한 페이지에 보여줄 게시물 수
$num_per_page = 5;
그리고 제 데이터베이스에 얼마나 게시물이 있는지 확인하겠습니다.
//전체 게시물 수 조회
$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의 값을 가져온다
참.. 개수 하나 알아내려고 4줄이나 필요하네요.
sql문에 count(*) as 함수 이용했습니다!
그다음에.. 이제 총 게시물 수랑 한 페이지당 5개랑 나눠서 페이지가 얼마나 필요한지 코딩하겠습니다
//전체 페이지 수
$total_pages = ceil($total_posts / $num_per_page);
ceil() 함수는 만약 () 안에 값이 실수형이면 올림 해서 정수로 표현되게 하는 것입니다! ex) ceil(3.14) => 4 반환
페이지 수가 소수점이 있을 수가 없죠
다음에는 각 페이지마다 시작하는 번호를 담는 변수를 만들기 전에!
저희는 1페이지 볼 때랑 2페이지 볼 때의 변수를 $page로 만들어서 설정하겠습니다
//현재 페이지 번호
if(isset($_GET['page'])) {
$page = intval($_GET['page']);
} else {
$page = 1;
}
만약에 GET방식에 page가 있으면 intval로 정수형으로 바꾸고 새로운 GET방식의 page를 받습니다.
무슨 말이면 저희가 1페이지를 보고 있다가 3페이지로 넘어갈 때 get방식으로 page에 3을 담아서 보내는 것입니다!
intval은 GET방식이 url에 담아서 보내는 거라 사람들이 실수든 뭐든 정수가 아닌 3.1 이렇게 적을 수 있기에
정수형으로 바꾸게 했습니다.
board.php에 처음 들어가면 GET방식으로 page을 받은 게 없을 테니 else문에 첫 페이지인 1을 넣었습니다.
이제 다음에는 각 페이지마다 시작하는 번호를 담는 변수를 만들겠습니다
//각 페이지 시작 인덱스
$start = ($page - 1) * $num_per_page;
-1을 하는 이유가 있습니다. 왜냐하면 저희는 이 start 변수로 데이터베이스 조회할 건데요
배열은 0부터 시작이기 때문에 1을 뺍겁니다!
그다음에 검색이 입력된 경우에 검색된 게시물이 몇 개인지 확인하겠습니다.
//검색이 입력된 경우
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%'";
}
$total_sql문이 검색된 게시물 수를 카운터 하는 구문입니다!
그리고 sql문에 ORDER BY이용해 각 인덱스마다 얼마다 나오게 하는지 코딩하겠습니다
//sql문에 추가로 작성하고 LIMIT 설정하고 DESC 즉 내림차순으로 정렬
$sql .= " ORDER BY board_id DESC LIMIT $start, $num_per_page";
SQL 언어에서 .= 는 본래 작성된 sql문에 뒤에 추가로 붙이겠다는 의미입니다!
즉 저 코드는 제가 전에 작성했던 sql문 SELECT board_id,id,title FROM $db_board 여기 뒤에 붙여지겠죠.
DESC는 내림차순으로 정렬하는 것이고요 LIMIT는 개수를 한정하는 겁니다. 즉 $start 부터 $num_per_page까지
나오게 하는 거죠
그다음에 sql문이 실행되고 출력하게 되겠죠?
그리고 마지막에 페이지 번호도 적고 GET으로 어느 페이지로 갔는지 작성하겠습니다!
echo '<p> [';
// 페이지 링크 출력
for ($i = 1; $i <= $total_pages; $i++) {
if($i == $page) {
echo $i.' ';
} else {
echo '<a href="?page=' . $i .'">'.$i. '</a>';
}
}
echo ' ]</p>';
이렇게요
만약 현재 페이지가 i랑 같으면 그냥 아무 링크 없이 i 출력하고
아니면 그 페이지의 링크 걸게 했습니다.
이러면 끝입니다!
한번 실행해 보겠습니다.
일단 임의로 게시판을 많이 만들어 놓겠습니다.
그리고 확인했더니
그리고 2페이지로 가보겠습니다
근데 약간만 더 수정하겠습니다! 너무 깔끔해 보이지 않네요
echo '<p> [ ';
// 페이지 링크 출력
for ($i = 1; $i <= $total_pages; $i++) {
if($i == $page) {
echo $i.' ';
} else {
echo '<a href="?page=' . $i .'">'.$i. '</a> ';
}
echo ' ';
}
echo ' ]</p>';
끝에 띄어쓰기 추가 했습니다
깔끔하네요!
근데 하이퍼 링크 때문에 페이지 색이 바뀌어서 뭔가.. 현재 페이지가 몇 페이지인지 구별하기 힘드네요!
그러니 조금만 더 수정하겠습니다
echo '<p> [ ';
// 페이지 링크 출력
for ($i = 1; $i <= $total_pages; $i++) {
if($i == $page) {
echo '<strong>'.$i.' </strong>';
} else {
echo '<a href="?page=' . $i .'">'.$i. '</a> ';
}
echo ' ';
}
echo ' ]</p>';
strong 구문 사용했습니다!
다시 보면
저렇게 강조되어 있는 게 보입니다
아무것도 작성 안 했는데 올라가지네요
이것부터 수정하겠습니다.
write_board.php로 가겠습니다.
그리고 수정하겠습니다
꼭 있어야지만 작성되게요!
input 구문에 required 추가해서 꼭 작성하게 하겠습니다.
<form action="write_process_board.php" method="POST">
<p><input type="text" name="title" maxlegth="44" placeholder="제목 입력, 최대 44자까지 가능합니다" required></p>
<p><textarea name="detail" rows="20" cols="20" maxlength="254" placeholder="내용 작성,최대 254자 가능합니다" required></textarea></p>
<p><input type="submit" value="올리기"></p>
</form>
좋아요!
다시 해보면
그다음 문제로는 저희가 페이지를 잘 나오게 했는데 모든 페이지 번호가 나오고 있습니다!
그래서 저는 이렇게 만들겠습니다
1~10까지 나오고 10부터는 20까지 보이게 하겠습니다!
즉 저는 페이지 번호를 블록처럼 만들겠습니다
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>';
}
// 페이지 링크 출력
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 ($block_start+10 < $total_pages) {
// 다음 페이지 블록이 있다면, 다음 버튼을 출력합니다.
$next_block_start = $block_start + 1;
echo '<a href="?page=' . $next_block_start .'">다음</a>';
}
echo ' ]</p>';
보시면은 floor 함수는 내림 함수입니다. 3.5이면 3을 반환합니다.
$block_start 에 page을 1 빼고 10 나누고 10을 다시 곱합니다.
이 말은 page가 1이면 block은 0부터 시작한다는 걸 의미하죠
만약 page가 11이면 block은 10부터 시작하겠죠!
이전 페이지는 현 페이지보다 1보다 크면 무조건 이전 페이지 글씨가 보이게 하고
링크를 걸었습니다!
그리고 for 문에서는 block_start에서 1을 더한 값이 시작입니다.
블록이 0이면 1부터 출력, 10이면 11부터 출력하기 위함이죠
min($block_start+10, $total_pages) 이 코드는 만약 1부터 시작이면 10까지 보이게 하고
11부터 시작이면 20까지 보이게 해주는 코드입니다. min은 이 둘 중 작은 값으로 반환하는 거고요.
그리고 if 절에 $block_start+10 < $total_pages 이면 다음 페이지 블록이 있다는 걸 뜻합니다
그래서 다음 글씨에 링크 걸어서 $next_block_start에 현 block에 11을 더하여 바로 다음 페이지 보게 했습니다.
이제 봐보겠습니다!
만약 다음 페이지랑 그저 한 페이지만 넘기는 페이지를 구현하고 싶으시면
// 다음 버튼 출력
if ($page < $total_pages) {
echo '<a href="?page=' . ($page+1) .'">다음</a> ';
}
이렇게 하면 되겠죠!
이전 버튼은 이전 페이지 아래에 작성하겠습니다
// 이전 버튼 출력
if ($page > 1) {
echo '<a href="?page=' . ($page-1) .'">이전</a> ';
}
뭔가 글씨로 보니깐 보기가 안 좋네요
이전페이지를 <<로 바꾸고
이전을 <
다음 페이지를 >>로 바꾸고
다음을 >로 바꾸겠습니다
오늘은.. 이렇게 페이징 기능을 넣어 봤습니다. 생각보다 많이 힘들고 이해하기가 어려워서
당황했습니다! 다음에는 파일 업로드 가능하게 하는 기능을 넣겠습니다! 감사합니다.
-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 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.'작성함</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>
-write_board.php
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>게시판 작성 중</title>
</head>
<body>
<h1>게시판 작성!</h1>
<?php
session_start(); //세션 시작
if(!isset($_SESSION['login_id'])) {
//로그인하지 않은 사용자
header("Location: login.php"); //login 화면으로 바꾼다
exit(); //이 페이지를 바로 닫는다
}
?>
<form action="write_process_board.php" method="POST">
<p><input type="text" name="title" maxlegth="44" placeholder="제목 입력, 최대 44자까지 가능합니다" required></p>
<p><textarea name="detail" rows="20" cols="20" maxlength="254" placeholder="내용 작성,최대 254자 가능합니다" required></textarea></p>
<p><input type="submit" value="올리기"></p>
</form>
<form action="board.php">
<p><input type="submit" value="돌아가기"></p>
</form>
<p>
<?php session_start();
if (isset($_SESSION['write_error'])) {
echo $_SESSION['write_error'];
unset($_SESSION['write_error']);
}
?>
</p>
</body>
</html>
'개발과제' 카테고리의 다른 글
[노말틱 모의 해킹 취업반 8주차 개발과제 ] 게시판 만들기(4) - 조회수 기능 (0) | 2023.04.19 |
---|---|
[노말틱 모의 해킹 취업반 8주차 개발과제 ] 게시판 만들기(4) - 파일 업로드 (0) | 2023.04.18 |
[노말틱 모의 해킹 취업반 6주차 개발과제 ] 게시판 만들기(2) - 수정, 삭제, 검색 (0) | 2023.04.16 |
[노말틱 모의 해킹 취업반 5주차 개발과제 ] 게시판 만들기(1) - 리스트 확인, 읽기, 쓰기 (0) | 2023.04.13 |
[노말틱 모의 해킹 취업반 4주차 개발과제 (2/2)] 회원가입 만들기-2 (0) | 2023.04.12 |