jineecode

php로 게시판 구체적으로 구현하기 (1) 본문

php

php로 게시판 구체적으로 구현하기 (1)

지니코딩 2021. 4. 5. 14:53

먼저 저는 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 링크를 누르면 토탈 페이지로 넘어갑니다.

 

 

깃허브

 

 

 


참조한 페이지

 

http://www.itmembers.net/board/view.php?id=php&page=2&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=19&PHPSESSID=7e61cd0e106f75d94b919bf63fc41726

 

www.itmembers.net

위 사이트의 도움을 정말 많이 받았다.

'php' 카테고리의 다른 글

php로 게시판 구체적으로 구현하기 (2)  (0) 2021.04.05
검색 폼 유형  (0) 2021.03.31
다음 글, 이전 글 php로 구현하기  (0) 2021.03.30
nl2br로 줄바꿈을 한 textarea의 수정?  (0) 2021.03.29
Comments