아~ 이번에도 코드가 어려워. 아마도 ‘요기보드’에서도 제일 복잡한 파일이 아닐까 싶어.
데이터베이스에 저장된 게시글을 가져와서 테이블에 배치하는 코드를 담당하는 파일이야.
여기는 특히 Html, php, MySQL 언어들이 뒤섞여 사용되어 더 어려워 보여.
여기도 큰 윤곽을 살펴 볼까?
<?php
if (!defined('YOGI')) exit ; // 개별 페이지 접근 불가
if (isset($_SESSION['ssuno']) AND $_SESSION['sslevel'] >= $write_level) { //회원등급이 지정등급 이상인 경우에만 [추가]버튼 보이게
echo ' <div style="float:right; margin-bottom:10px">'."\n";
echo ' <a class="w3-button w3-blue w3-small" href="'.$_SERVER['PHP_SELF'].'?mode=add&'.$pre_url.'">글쓰기</a>'."\n";
echo ' </div>'."\n";
}
//******** 관리자 모드 (관리자 페이지에서 최신글 볼때 )************************************************************
if ($isAdminMode == true) {
echo '<table class="w3-table w3-bordered">'. "\n";
... 생 략 ...
echo "</table>\n";
//******** 일반 사용자 모드 ***************************************************************************************
} else {
echo '<table class="w3-table w3-bordered" style="table-layout:fixed;">'. "\n";
... 생 략 ...
echo "</table>\n";
}
mysqli_close($dbc);
//---- 1페이지가 넘으면 하단에 페이지 링크 생성
if ($num_pages > 1) {
include_once(YOGI_DIR . '/page_links.php'); // 페이지 링크
echo " <div class='w3-center w3-small w3-margin-top'>\n";
echo generate_page_links($cur_page, $num_pages, $search);
echo " </div>";
}
?>
▶ if (!defined('YOGI')) exit
바로 전 장 bbs.php 에서 설명했지?
이 bbs_list.php 도 프로그램 조각이기 때문에 브라우저 주소줄에서 바로 쳐서 들어 오지 못하게 막은거야.
▶ if (isset($_SESSION['ssuno']) AND $_SESSION['sslevel'] >= $write_level)
세션(SESSION) 에 대해서는 아직 설명을 안했지만 로그인을 하게 되면 회원번호와 등급이 $_SESSION['ssuno'] 와 $_SESSION['sslevel'] 라는 전역변수에 저장이 되고 있어.
그러니까 여기서 사용자번호가 있고(즉, $_SESSION['ssuno'] 가 있고), 회원등급이 $write_level 이상이면 [글쓰기] 버튼을 보이게 해라.. 라는 조건문이야.
notice.php 에서 $write_level = 8 로 정했으니까 이 게시판에서는 회원등급이 8 이상인 회원이 로그인했을 경우에만 [글쓰기]버튼이 보이겠지?
(보통 공지사항은 관리자급 이상만 쓸 수 있잖아.. 그래서 등급을 8 로 정했어. $write_level 을 몇으로 하느냐는 관리자 마음이겠지?)
▶ if ($isAdminMode == true) {
} else {
}
코드가 긴 것 같지만 자세히 보면 거의 비슷한 2개의 코드로 나뉘어 있어.
위 if 조건문에 따라 ($isAdminMode == true) 이면 아래 줄의 게시글 테이블을 만드는 코드와,
아니면 else 아래의 게시글 테이블을 만드는 코드로 나뉘어.
그럼 이 $isAdminMode 는 어디서 온 변수일까?
이것은 admin 폴더 안의 admin_bbs.php 에서 생성한 변수야.
admin_bbs.php 는 관리자페이지에 있는 [최근 게시글]을 클릭했을 때 실행되는 파일로, 모든 게시판에 올라 온 새 게시글, 댓글 등을 감시하는 기능을 해.
이 admin_bbs.php 안을 보면 $isAdminMode = true 로 변수를 생성한 뒤에 include() 로 bbs.php 를 부른 것을 알 수 있어.
그리고 bbs.php 에서는 다시 include_once(YOGI_DIR . '/bbs_list.php') 라인을 만나서 이 자리에 오게 된거지.
그러므로 [최근 게시글]를 실행하면 $isAdminMode 값이 true 가 되고, 다른 공지사항, 게시판 같은 게시판에서는 이 변수가 없기 때문에 아래 else 아래의 테이블이 만들어 지겠지?
관리자페이지용 페이지는 별로 쓸 일이 없으니 아래쪽 일반 회원들이 보는 테이블만 공부해 보자구..
echo '<table class="w3-table w3-bordered" style="table-layout:fixed;">'. "\n";
echo ' <thead class="w3-gray">'. "\n";
echo ' <tr><th width=100px>날짜</th><th>제 목</th><th width=100px>작성자</th><th width=50px>조회</th></tr>'. "\n";
echo ' </thead>'."\n";
echo ' </tbody>'."\n";
if (empty($results_per_page)) {$results_per_page = 10;} // 페이지당 출력수 지정안하면 기본값 10줄로..
$skip = (($cur_page - 1) * $results_per_page);
//---- DB접속
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME) or die('DB 접속에러 bbs_list-요기4');
//---- 검색결과와 총갯수, 페이지수 계산
if (empty($search)) {
$query = "SELECT `bno`, `datetime`, `subject`, `cmt`, `hit`, `writer` FROM yg_bbs WHERE catno=$catno AND parent=0 ORDER BY `datetime` DESC" ;
} else {
$query = "SELECT `bno`, `datetime`, `subject`, `cmt`, `hit`, `writer` FROM yg_bbs WHERE catno=$catno AND parent=0 AND (subject LIKE '%$search%' OR content LIKE '%$search%') ORDER BY `datetime` DESC" ;
}
$result = mysqli_query($dbc, $query) OR die('검색 쿼리에러 bbs_list-요기5');
$total = mysqli_num_rows($result);
$num_pages = ceil($total / $results_per_page);
//---- 현재 페이지의 내용만 가져 오는 쿼리
$query = $query . " LIMIT $skip, $results_per_page";
$result = mysqli_query($dbc, $query) or die('쿼리에러 in bbs_list-요기6');
if (mysqli_num_rows($result) == 0) $num_pages += 1; // 마지막 페이지에 1개 있던 글을 지우면 전체페이지+1 해서 빈페이지를 보여줌
while ($row = mysqli_fetch_array($result)) {
echo ' <tr>';
// 일반모드에서는 날짜만 표시하고, 해당 글에 링크걸기 (일반모드에서는 댓글은 안보이므로 해당글은 모두 부모글이다)
echo ' <td>' . substr($row['datetime'],2,8) . '</td>';
echo ' <td class="w3-left-align bbslink"><a href="'.$_SERVER['PHP_SELF'].'?mode=view&bno='.$row['bno'].'&'.$pre_url.'">'.$row['subject'].'</a>';
if ($row['cmt']) { //-- 댓글이 있으면 댓글수 표시
echo ' <span class="w3-text-red">(' . $row['cmt'] . ')</span>';
}
echo '</td>';
echo ' <td class="bbs_noflow">' . $row['writer'] . '</td><td>' . $row['hit'] . '</td>';
echo '</tr>' . "\n";
}
echo " <tbody>\n";
echo "</table>\n";
공지사항(notice.php) 에서 시작된 코드라고 가정하고 설명할께..
첫 5 줄 정도는 테이블을 생성하기 위한 html 과 css 코드들이야. 그대로 출력되겠지?
▶ if (empty($results_per_page)) {$results_per_page = 10;}
만일 notice.php 에서 bbs.php 를 부르기 전에 $results_per_page (한페이지당 게시글갯수)를 지정하지 않고 왔다면 기본값을 10 으로 해라.
▶ $skip = (($cur_page - 1) * $results_per_page)
여기서 여러분의 수학적 능력이 필요해.
한페이지에 10 개씩 보여 준다고 했을 때, 현재 게시판에 올라온 글이 총 90 개면 총 9 개의 페이지가 있게 되겠지? 웹사이트에서 이 페이지 번호는 보통 테이블 아래에 1 2 3 4 같은 형식으로 보여줘.
그런데 현재 5 페이지를 보고 있다고 가정해봐.
그러면 게시글 1~40 번째 까지의 글을 필요없어.
이때는 yg_bbs 테이블에서 41~50 사이의 글만 가져 와서 보여 줘야해.
그럼 DB 에서 읽어 올 때 건너 뛰어야 할 갯수는 아래 공식으로 계산할 수 있어.
(현재 선택한페이지 -1) * 페이지당 게시글 갯수
현재 5페이지를 클릭했다면, 이 공식을 대입하면
(5 - 1 ) * 10 = 40 이 되겠지?
이 건너 뛸 갯수를 $skip 변수에 넣어 두고 있는 코드야.
▶ if (empty($search)) {
$query = "SELECT , . . 생략 . . WHERE catno=$catno AND parent=0 ORDER BY `datetime` DESC" ;
} else {
$query = "SELECT . .생략. . WHERE catno=$catno AND parent=0 AND (subject LIKE '%$search%' OR content LIKE '%$search%') ORDER BY `datetime` DESC" ;
}
DB로 날릴 쿼리문을 작성하는데 화면의 [Search..] 자리에 검색어를 입력했느냐, 아니야에 따라 검색어가 조금 달라.
공통적인 것인 catno 가 notice.php 에서 지정한 번호와 같고 parent 필드값이 0 인 파일들만 가져 오라는 거야. (parent 항목에 번호가 있으면 이건 댓글이야. 여기서는 댓글을 빼고 본 게시글만 가져오는 쿼리문을 작성하고 있어)
또 가져오는 순서(ORDER BY)는 datetime 필드의 역순(DESC)으로 검색해서 가져 오라고 했어.
▶ $result = mysqli_query($dbc, $query)
위 쿼리문을 DB 로 날려서 결과를 가져와.
▶ $total = mysqli_num_rows($result)
위 쿼리문에 해당 되는 데이터 갯수가 총 몇 개인지 알려 주는 함수야. 결과를 $total 에 저장해 둬.
▶ $num_pages = ceil($total / $results_per_page)
총 갯수를 페이지당 출력갯수(10) 으로 나누면 총 몇 페이지가 필요한지 나오겠지?
하단의 페이지 링크를 몇 개를 만들어야 하는지 알 수 있어.
다시 쿼리를 한 번 더 보내는데 이번에는 지금 페이지에 해당하는 데이터만 가져 오는 거야.
이전 쿼리문 뒤에 LIMIT $skip, $results_per_page 가 추가 되는거야.
PHP 에서는 두 개의 문자열을 붙이는 기호가 점(.) 이라고 했지?
그러니 $query = $query . ' LIMIT...' 라는 문장은 앞의 $query 내용 뒤에 'LIMIT...' 라는 문장이 될거야.
MySQL 에서 LIMIT 는 검색결과에서 지정한 갯수 만큼만 가져 오라는 옵션이야.
사용방법은 다음 두 가지가 있어.
① LIMIT 가져올 갯수
② LIMIT 시작번호 , 가져올 갯수
예를들어 SELECT 의 조건에 해당하는 결과가 총 10 개 인데 문장 맨 뒤에 LIMIT 2 라고 쓰면 2개만 가져오고,
맨 뒤에 LIMIT 5 , 2 라고 쓰면 10개의 결과 중 6번째 부터 2개만 가져 오라는 뜻이야.
(MySQL 에서도 첫번째는 0 부터 시작하기 때문에 5 는 6번째 자료를 뜻해)
이제 위에서 만든 $skip = 40 이고, $results_per_page = 10 이니 문장을 다시 해석하면.
"SELECT ... FROM yg_bbs WHERE ..... LIMIT 40 , 10"
로 계산되어 질거야.
즉 "앞쪽 40 개는 건너 뛰고 10개만 가져 와라!" 가 되겠지?
이 LIMIT 에 대해서 더 궁금하면 구글이나 W3Schools 등에서 검색해 보도록 해.
▶ $result = mysqli_query($dbc, $query)
while ($row = mysqli_fetch_array($result))
자 이렇게 완성된 쿼리문을 보내면 원했던 결과만 $result 배열변수 안에 들어 오겠지?
그리고 while 반복문을 사용해서 배열의 내용을 하나 씩 꺼내서 ( mysqli_fetch_array($result) ) 항목별로 echo 명령으로 테이블의 td 태그 안에 넣어 주고 있어.
while 반복문이 끝나면 이제 </tbody> </table> 로 테이블을 닫고 mysqli_close($dbc) 명령으로 DB를 닫는 것으로 이 bbs_list.php 의 할 일은 끝나는 거야.
휴~ 설명하기 진짜 힘드네.
어때 이해가 좀 돼?
그런데 이해가 좀 안 와도 괜찮아. 이해가 없어도 요기보드는 잘 작동할테니까...
코드 맨 아래쪽은 테이블 아래에 페이지 링크를 만드는 코드들이 있는데 이것은 일단 생략할께..
(왜냐하면 지금까지 설명 보다 훨씬 더 복잡해서... 여러분이 포기할까봐...)