반응형




게시판 페이징.. 고난과 역경의 연속..


게시판 페이징 만들려고 며칠 간 헤매고 이해안되서 멘붕이었다가 어찌어찌 구현이 되어서 정리해볼까 합니다.


혹시나 저와 같은 어려움을 겪고 계시는 분이 있으시다면 이 글이 도움이 되었으면 좋겠네요.


제가 만들려고 한 페이징은 이런 모습입니다.



10개씩 보여주고 10개씩 넘어가는 페이징 입니다.


그럼 시작해볼게요





먼저 페이징을 어떻게 할지 생각해봅니다. 

한 페이지에 게시글은 몇 개를 보여줄 것인가.

페이지 번호는 몇 개까지 보여줄 것인가.


저 같은 경우는 이 두개가 항상 헷갈려서 변수명 부터 애를 먹었습니다.


그러면 변수명을 지정하겠습니다.

$pageNum

이 변수는 1 2 3 4 5 6 7 8 9 10 이러한 번호 하나하나를 의미합니다.


$list

이 변수는 한 페이지에 몇 개의 글을 보여줄지 정하는 변수입니다. 

만약 $list = 50 이라면 한 페이지당 50개의 글 목록이 나타나게 됩니다.



먼저 처음에 이 두 변수를 지정해주었습니다.

저는 GET방식으로 페이지 번호를 누르면 주소에 페이지값을 전달하는 방식입니다.


$pageNum = ($_GET['page']) ? $_GET['page'] : 1;     

// 삼항 연산자로 pageNum값이 비어있을때 에러를 방지 하기 위해 pageNum은 초기값 1로 지정해놓았고 

//page는 pageNum이랑 같다고 보시면 됩니다.

//($_GET['page']) = 값을 받아

// ? $_GET['page'] = 값이 있으면 그대로  $_GET['page']  값을 사용하고

//  : 1  = 비어있다면 1로 값을 지정하라는 조건문 입니다.



$list = ($_GET['list']) ? $_GET['list'] : 50; //page : default - 50

//list도 마찬가지로 설정해놓았고 한 페이지에 50개의 글 목록을 보여주게 하겠습니다.







이제 페이징을 만들기 위한 여러 조건들을 정의하겠습니다.



$b_pageNum_list = 10;

//b는 block의 약자라고 생각하시면 됩니다. 블럭에 나타낼 페이지 번호 갯수 입니다. 


$block = ceil($pageNum/$b_pageNum_list);

//현재 리스트의 블럭을 구하는 식 입니다. 




여기서 블럭이란

저 검은상자가 블럭입니다. $b_pageNum_list = 10개이기 때문에 10까지만 나타난 상태구요.

$block = ceil($pageNum/$b_pageNum_list); 이 식은 예를 들면 현재 위 사진의 블럭은 1~10까지 있는 첫번째 블럭입니다.

11~20까지 있는 블럭은 2가 되겠죠. 이런 식으로 계산해주는 식입니다.


계산을 한번 해보겠습니다.

아 ceil 이란 함수는 소수점을 다 올려주는 역할입니다. 1.2든 1.7이든 다 2로 계산해주죠.

현재 페이지 $pageNum가 7페이지라고 가정하고

 $b_pageNum_list는  10으로 정해놨으니 계산하면 0.7이 나오죠?

그럼 올림해주면 1이 됩니다. 현재는 첫번째 블럭에 머물러있다고 판단할 수 있죠.

위에서 설명드렸듯이 1~10 까지 있으면 첫번째 블럭이라고 하였으니 7페이지는 첫번째 블럭에 있어야 하죠.





그럼 다음 블럭 조건을 정하겠습니다.


 

$b_start_page = ( ($block - 1) * $b_pageNum_list ) + 1; 

//현재 블럭에서 시작페이지 번호


$b_end_page = $b_start_page + $b_pageNum_list - 1; 

//현재 블럭에서 마지막 페이지 번호



블럭의 시작과 마지막 페이지 번호를 구하는 변수 입니다.

대입해서 계산해보면 

$block은 현재 첫번째 블럭이니 1 입니다. 여기서 -1을 빼면 0이 나오고

$b_pageNum_list는 10이라고 정했으니 곱해봤자 0이 나옵니다. 마지막으로 1을 더하면

첫번째 블럭의 시작페이지는 1이 됩니다.


만약 두번째 블럭을 구한다고 봤을때 $block은 2가 되고

$b_pageNum_list는 10이니

((2-1) * 10) + 1 = 11 이 나옵니다.

두번째 블럭의 시작번호니 11이 맞습니다.


그럼 마지막 페이지 번호는 위에서 구한 시작페이지 번호를 이용하여 계산합니다.

두번째 블럭 마지막 페이지 번호를 구해보면 $b_start_page는 11이고

$b_pageNum_list는 10이니

11+10-1=20

두번째 블럭의 마지막페이지는 20 입니다.





이제 총 게시글의 페이지 수를 구하겠습니다.



$total_page = ceil( $total_count / $list ); 

// $total_count는 글의 총 갯수이므로 게시판 db에서 count(*) 쿼리로 계산해주시면 됩니다.



총 게시글의 페이지수는 

총 글의 갯수 나누기 페이지당 보여줄 갯수로 나눕니다.

처음에 저는 50개씩 보여주려고 해서 $list = 50 으로 정했습니다.

그래서 50으로 나눠주면 페이지 수가 나오겠죠. 

ceil을 해준 이유는 151개의 글이 있다고 가정했을때

151/50 계산하면 3.x가 나옵니다. 이걸 올림하면 4가 되죠

50으로 나누면 1개의 글이 남죠? 이것도 페이지에 보여주기 위해 4페이지까지 만들어주는 겁니다.





이제 하나만  더 설정해주고 페이징을 구현해보겠습니다.


 

if ($b_end_page > $total_page) 

$b_end_page = $total_page;


이 조건은 어떤 상황을 위한 조건이냐면 블럭의 마지막 페이지가 총 페이지 수보다 클 때 두 숫자를 같게 해주는 조건입니다.

만약 총 페이지 수는 15 페이지 인데 블럭의 마지막 페이지가 20일 경우가 생깁니다. 

이러한 경우는 우리가  $b_end_page = $b_start_page + $b_pageNum_list - 1; 이런 변수를 설정해주어서 생기는 문제입니다.

이 변수에 따르면 무조건 10개씩 계산되어 10단위로 마지막페이지가 끝나게 됩니다.

그래서 총 페이지 수가 15페이지까지 밖에 없는데 마지막 페이지는 20페이지까지 생성되게 됩니다. 

그럼 16페이지부터 20페이지는 아무런 글도 없이 빈 목록이 나타나게 되는거죠.

그래서 총 페이지수랑 마지막 페이지를 같게 맞춰주는 겁니다.



현재 131페이지이고 여기까지 밖에 글이 없는데도 140페이지까지 나오게 하고 있습니다.


132로 넘어가면 자료가 없다고 뜹니다. 140번까지도 마찬가지죠

(자료가 하나도 없습니다.는 제가 따로 설정해주어서 나타나는 메세지입니다.)



이제 위 조건을 주면

딱 글이 있는 페이지만 출력하게 됩니다.






이제 페이징 구현을 해보겠습니다.

먼저 처음으로 가는 버튼을 만들겠습니다.


if($pageNum <= 1){?> //페이지번호가 1보다 작거나 같다면

<font size=2  color=red>처음</font> //링크없이 그냥 처음이라는 문자만 출력합니다.

<?}else{?> //1보다 크다면

<font size=2 ><a href="/yw/buypaging.php?page=&list=<?=$list?>">처음</a></font>

//링크 걸린 처음을 출력합니다. 

<?}

보기쉽게 코드버전으로 추가했습니다. 위와 같은 내용입니다.

1
2
3
4
5
6
7
8
9
10
11
12
 
if($pageNum <= 1){?> //페이지번호가 1보다 작거나 같다면
        <font size=2  color=red>처음</font> //링크없이 그냥 처음이라는 문자만 출력합니다.
 
    <?}else{?> //1보다 크다면
 
        <font size=2 ><a href="/yw/buypaging.php?page=&list=<?=$list?>">처음</a></font>
 
        //링크 걸린 처음을 출력합니다. 
 
    <?}
cs

여기서

<a href="/yw/buypaging.php?page=&list=<?=$list?>">

이 부분은 실제 주소창에 나오는 부분입니다.page= 페이지가 나타나는 부분이고 &list는 50개가 나올 것입니다.


예를 들면 2페이지라면

yonoo88.tistroy.com/yw/buypaging.php?page=2&list=50

이렇게 나타납니다.



처음으로 가는 링크버튼은 무조건 1페이지로 가면 됩니다. 그래서 조건을 1보다 작거나 같을때로 주었고 

<font>태그로 색깔은 color='red' 빨강으로 해주었구요.

1페이지에 있을때는 처음버튼이 필요없으므로 링크를 안 걸어주었습니다. 



현재 1페이지에 있을때 상태. 처음 글자에 링크가 안 걸려있다


2페이지 일 때 처음버튼에 링크가 걸려있다.


이렇게 구현해주기 위한 부분이었습니다.

아 그리고 중간 중간 <? ?> 이 표시는 php때문에 사용하였습니다. 

php안에 echo를 사용해서 html을 구현하는 방식도 있는데 

저는 html태그안에 php를 사용하는 방식으로 했습니다.







이제 10개씩 거꾸로 가는 이전 링크를 만들겠습니다.


if($block <=1){?>  //block이 1보다 작거나 같으면 

<font> </font> //더 이상 거꾸로 갈 수 없으므로 아무 표시도 하지 않습니다.

<?}else{?> //block이 1보다 크다면

<font size=2><a href="/yw/buypaging.php?page=<?=$b_start_page-1?>&list=<?=$list?>">이전</a></font>

//이전 링크를 보여줍니다.

<?}


보기쉽게 코드버전으로 추가했습니다. 위와 같은 내용입니다.

1
2
3
4
5
6
7
8
9
10
11
if($block <=1){?>  //block이 1보다 작거나 같으면 
    <font> </font> //더 이상 거꾸로 갈 수 없으므로 아무 표시도 하지 않습니다.
 
<?}else{?> //block이 1보다 크다면
 
    <font size=2><a href="/yw/buypaging.php?page=<?=$b_start_page-1?>&list=<?=$list?>">이전</a></font>
 
    //이전 링크를 보여줍니다.
 
<?}
cs

이전 링크가 나타납니다.


더 이상 뒤로 갈게 없으니 이전링크를 나타내지 않습니다.



block은 우리가 처음에 $block = ceil($pageNum/$b_pageNum_list); 라고 구현을 해놓았었습니다.

block이 1이면  처음이라는 뜻이 되겠죠


하지만 1보다 크다면

<font size=2><a href="/yw/buypaging.php?page=<?=$b_start_page-1?>&list=<?=$list?>">이전</a></font>

이전 링크를 만들어 줍니다. 여기서 중요한 건 page=<?=$b_start_page-1?> 이 부분인데

$b_start_page 이거는 블럭의 시작 페이지변수 입니다.

즉 시작 페이지에서 1을 빼주면 이전 블럭으로 가게되는거죠.


여기서 시작페이지는 11입니다. 여기서 1을 빼면 10이 되겠죠?


보시면 10페이지에 위치되어 있습니다. 이런 식으로 처음과 끝에 1을 더하고 빼면서 block간 이동을 하게 됩니다.






이제 진짜인 페이징 번호를 구현하겠습니다.

 //$b_start_page를 $j의 초기값으로 설정 ; $b_end_page보다 작거나 같을때 까지 for문 돌리기 ; $j++하나씩 증가시키기

 for($j = $b_start_page; $j <=$b_end_page; $j++)

{

if($pageNum == $j) //pageNum 와 j 가 같으면 현재 페이지 이므로

{?>

<font size=2 color=red><?=$j?></font>//링크걸지 않고 그냥 현재페이지만 출력

<?}else{?> //서로 다르다면

              <font size=2><a href="/yw/buypaging.php?page=<?=$j?>&list=<?=$list?>"><?=$j?></a></font>

               // 현재 페이지를 제외한 나머지 페이지번호를 링크를 달아 출력하기

<?}

}





















보기쉽게 코드버전으로 추가했습니다. 위와 같은 내용입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//$b_start_page를 $j의 초기값으로 설정 ; $b_end_page보다 작거나 같을때 까지 for문 돌리기 ; $j++하나씩 증가시키기
 
 for($j = $b_start_page; $j <=$b_end_page; $j++)
{
    if($pageNum == $j) //pageNum  j  같으면 현재 페이지 이므로
    {?>
        <font size=2 color=red><?=$j?></font>//링크걸지 않고 그냥 현재페이지만 출력
 
    <?}else{?> //서로 다르다면
 
              <font size=2><a href="/yw/buypaging.php?page=<?=$j?>&list=<?=$list?>"><?=$j?></a></font>
 
               // 현재 페이지를 제외한 나머지 페이지번호를 링크를 달아 출력하기
 
    <?}
 
}
cs

for($j = $b_start_page; $j <=$b_end_page; $j++)

시작페이지인 $b_start_page와 마지막 페이지인 $b_end_page 만큼 for문이 돌아가도록 합니다.
block당 10개씩 돌아가게 하는거죠.
1~10까지 11~20까지 이런식으로요



if($pageNum == $j)

현재페이지인 $pageNum $j 가 같다면 현재 페이지를 의미하니



<font size=2 color=red><?=$j?></font>

$j를 빨간색으로 숫자를 표시하고  출력합니다.




현재페이지인 $pageNum  $j 가 다르다면 

 <font size=2><a href="/yw/buypaging.php?page=<?=$j?>&list=<?=$list?>"><?=$j?></a></font>

현재페이지를 제외한 다른 페이지 숫자에 링크를 걸어 이동할 수 있게 해줍니다. page= 이 부분에 $j를 넣어주면 3페이지를 클릭했을때 3이 들어가면서 그 페이지로 이동하게 되겠죠


이제 숫자 페이징 구현은 다 했습니다.

이제 다음 링크와 마지막 링크만 만들면 되겠네요


다음으로 가는 링크버튼을 만들어 보겠습니다.

이걸 만들기 전에 구해야될게 있는데 block의 총 갯수 입니다.


$total_block = ceil($total_page/$b_pageNum_list);


위에서 구했던 (총 페이지 갯수)에서 (블럭에 나타낼 페이지 번호 갯수)로 나누면 됩니다.

저는 왠지 모르겠지만 이게 이해가 그렇게 안됐습니다;;; 바본가봐

ceil을 해주면서 남는 페이지까지 포함해서 나타낼 수 있겠죠.






이제 다음 링크버튼 입니다.

 if($block >= $total_block){?>  //block 과 총 block 갯수와 값이 같다면

<font> </font>  // 맨 마지막 블럭이므로 다음링크버튼이 필요없어서 보여주지 않는다.

<?}else{?> //그게 아니라면

        <font size=2><a href="/yw/buypaging.php?page=<?=$b_end_page+1?>&list=<?=$list?>">다음</a></font>

//다음 링크버튼을 걸어 보여준다.

<?}











보기쉽게 코드버전으로 추가했습니다. 위와 같은 내용입니다.

1
2
3
4
5
6
7
8
9
10
11
 if($block >= $total_block){?>  //block 과 총 block 갯수와 값이 같다면
 
    <font> </font>  // 맨 마지막 블럭이므로 다음링크버튼이 필요없어서 보여주지 않는다.
 
<?}else{?> //그게 아니라면
 
        <font size=2><a href="/yw/buypaging.php?page=<?=$b_end_page+1?>&list=<?=$list?>">다음</a></font>
 
    //다음 링크버튼을 걸어 보여준다.
 
<?}
cs

이전 버튼과 같은 원리인데 다르다면 여기서는 page 변수에 +1을 더해주는 겁니다. 

<font size=2><a href="/yw/buypaging.php?page=<?=$b_end_page+1?>&list=<?=$list?>">다음</a></font>


$b_end_page 이거는 블럭의 마지막 페이지 변수였습니다. 거기서 +1을 해주면 다음 블럭의 시작 페이지 변수가 되겠죠

현재 마지막 페이지 10에 위치해 있습니다.



+1을 하면 11로 넘어가면서 두번째 블럭이로 이동합니다.




이제 마지막 링크버튼 입니다.


if($pageNum >= $total_page){?> //페이지 넘버와 총 페이지가 같다면

      <font size=2  color=red>마지막</font> 

//마지막 페이지이므로 링크없이 마지막만 빨간색으로 출력

<?}else{?> // 그게 아니라면

<font size=2><a href="/yw/buypaging.php?page=<?=$total_page?>&list=<?=$list?>">마지막</a></font>

//페이지변수를 total_page로 주어서 마지막으로 가는 링크버튼을 출력

<?}?>









보기쉽게 코드버전으로 추가했습니다. 위와 같은 내용입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
if($pageNum >= $total_page){?> //페이지 넘버와 총 페이지가 같다면
 
      <font size=2  color=red>마지막</font
 
    //마지막 페이지이므로 링크없이 마지막만 빨간색으로 출력
 
<?}else{?> // 그게 아니라면
 
    <font size=2><a href="/yw/buypaging.php?page=<?=$total_page?>&list=<?=$list?>">마지막</a></font>
 
    //페이지변수를 total_page로 주어서 마지막으로 가는 링크버튼을 출력
 
<?}?>
cs

$pageNum는 현재 페이지를 나타내고 이 변수가 total_page 변수와 같다는 것은 마지막 페이지라는 걸 의미합니다.

총 페이지 수와 마지막 페이지 수는 당연히 같겠죠? 

총 200페이지 책의 마지막 페이지 번호는 200페이지 일테니까요


$pageNum 와 $ total_page 이게 다르다면 마지막 페이지는 아니라는 의미이니

마지막 링크버튼을 나타내도록 합니다.

그래서 page= 에 <?=$total_page?> 를 넣어주게 되면 마지막 페이지로 넘어가게 됩니다.



마지막 링크버튼을 누르면

이처럼 링크없이 빨간색으로 마지막 글씨만 출력된다.


아 중요한게 하나 빠졌네요. 게시판 db에서 데이터를 가져올때 limit를 걸어주는 것입니다.

데이터를 전부 가져오고 50개씩 출력하는 건 데이터가 적을때는 상관없지만 

수십 수백만개 데이터가 있다면 전부 가져오는데 시간이 걸리기 때문에 속도도 느리고 사용자도 답답할 것입니다.


그래서 가져올때 전부 가져오지 않고 50개씩만 가져오게 하는 것입니다.

게시판을 다 만드시고 페이징만 남으셨다면 게시판db를 가져오는 것도 다 구현되어 있으실 것입니다.

그럼 그 쿼리 마지막에 limit $limit,$list 를 해주세요.

예를 들자면 select * from board limit $limit,$list 이런식으로요.

여기서 $limit는 시작점

(여기서 시작점은 글 번호가 아닌 list 페이지라고 볼 수 있겠네요. 50개씩 들어있는 페이지라고 보시면 될 것 같습니다.)

$list는 아시다시피 가져올 양입니다.



$list는 처음에 50개라고 정해놨었죠 그럼 $limit는

$limit = ($page - 1) * $list;


이걸로 구합니다. 여기서 주의할 점은 db에서는 0부터 시작한다는 점입니다.

출처

http://nolran.tistory.com/57

  1. //아래 예는 5개 가져오기  
  2. SELECT * FROM [TABLE NAME] LIMIT 5;  
  3.   
  4. // LIMIT 시작점, 갯수 (아래 예의 경우 5번째부터 10개 추출. 첫번째 파라미터는 0 부터 시작함!)  
  5. SELECT * FROM [TABLE NAME] LIMIT 4, 10;  



이렇게 페이징 구현을 마쳤습니다.

설명이 잘 됐으려나 모르겠지만 도움이 됐으면 좋겠네요.

처음으로 해보는 포스팅이라 문제점도 많을겁니다.

지적해주시면 감사하겠습니다.


마지막으로 페이징 부분 소스입니다.

클릭하시면 원본보기 가능합니다.




아무래도 보기 편한게 원본인거 같아서 캡쳐합니다.


밑에는 소스입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<!-- 페이징 그리기 -->
    <tr>
        <td height="30" align="center" valign="middle" colspan="50" style="border:1px #CCCCCC solid;">
<?
    $pageNum = ($_GET['page']) ? $_GET['page'] : 1;     //page : default - 1
    $list = ($_GET['list']) ? $_GET['list'] : 50//page : default - 50
 
 
    $b_pageNum_list = 10//블럭에 나타낼 페이지 번호 갯수
    $block = ceil($pageNum/$b_pageNum_list); //현재 리스트의 블럭 구하기
    
 
    $b_start_page = ( ($block - 1* $b_pageNum_list ) + 1//현재 블럭에서 시작페이지 번호
    $b_end_page = $b_start_page + $b_pageNum_list - 1//현재 블럭에서 마지막 페이지 번호
 
    $total_page =  ceil($buyTotalCount/$list); //총 페이지 수
 
    if ($b_end_page > $total_page
        $b_end_page = $total_page;
    
 
    if($pageNum <= 1){?>
        <font size=2  color=red>처음</font>
        <?}else{?>
            <font size=2><a href="/yw/buypaging.php?year=<?=$year?>&month=<?=$month?>&day=<?=$day?>&page=&list=<?=$list?>">처음</a></font>
        <?}
 
 
 
    if($block <=1){?>
        <font> </font>
    <?}else{?>
        <font size=2><a href="/yw/buypaging.php?year=<?=$year?>&month=<?=$month?>&day=<?=$day?>&page=<?=$b_start_page-1?>&list=<?=$list?>">이전</a></font>
    <?}
 
        
 
 
 
    for($j = $b_start_page$j <=$b_end_page$j++)
    {
 
        if($pageNum == $j)
        {?>
            <font size=2 color=red><?=$j?></font>
        <?}
        else{?>
            <font size=2><a href="/yw/buypaging.php?year=<?=$year?>&month=<?=$month?>&day=<?=$day?>&page=<?=$j?>&list=<?=$list?>"><?=$j?></a></font>
            <?
          }                
 
    }
 
 
 
    $total_block = ceil($total_page/$b_pageNum_list);
 
    if($block >= $total_block){?>
    <font> </font>
    <?}else{?>    
        <font size=2><a href="/yw/buypaging.php?year=<?=$year?>&month=<?=$month?>&day=<?=$day?>&page=<?=$b_end_page+1?>&list=<?=$list?>">다음</a></font>
    <?}
 
 
 
    if($pageNum >= $total_page){?>
 
            <font size=2 color=red>마지막</font>
        
        <?}else{?>
            <font size=2><a href="/yw/buypaging.php?year=<?=$year?>&month=<?=$month?>&day=<?=$day?>&page=<?=$total_page?>&list=<?=$list?>">마지막</a></font>
 
        <?}
    ?>
    </td>
 
    </tr>
cs




반응형

'지식메모 > PHP' 카테고리의 다른 글

php 문자열 공백제거하기  (1) 2013.11.13
문자열 분리하기 다루기  (0) 2013.10.08
게시판 글 번호 구하기  (2) 2013.08.13
날짜 출력 함수 사용하기  (0) 2013.08.05
문자열 잘라쓰기  (0) 2013.08.05

+ Recent posts