본문 바로가기
재밌는 IT 개발/그누보드 테마 제작기(記)

그누보드 테마 제작 23 - 게시글 부가 페이지 개발

by 행복한 만수킴 2020. 7. 10.

부가 페이지란, 아래 영역을 말하는겁니다.

생뚱맞게도 메일의 INBOX가 들어가 있다. ㅎㅎ

저 영역을 남겨두긴 했는데,
저기에 뭘 넣어야 할지 답을 못정하고 있다.
걍 없애버릴까도 잠깐 생각이...

sir.kr에서 찾아봐야겠습니다.

커뮤니티 최신글과 커뮤니티 인기글 캡처

아.. 기본테마에서도 찾아봐야겠어요.
별거 없네요...

SIR에서 가져온 본 게시판의 최신글과 인기글을 배치하고
그 아래로 최신 댓글을 위치시켜보겠습니다.

이번에도 작업 순서를 정해서 진행해볼게요.

1. 보기 페이지의 Side 영역을 위한 파일을 생성합니다.
2. Metronic Admin 템플릿을 이용하여 UI 만들기
3. 각 게시판의 최신글과 인기글을 돌려줄 쿼리 제작
4. 각 게시판의 최신 댓글과 인기 댓글을 돌려줄 함수 제작
5. /bbs/view_side.php 개발
6. view_side.skin.php 개발

이렇게 진행합니다.

1. 보기 페이지의 Side 영역을 위한 파일을 생성합니다.

/bbs/view_side.php : 보기 사이드 영역의 리스트를 개발합니다.
/theme/mt703/skin/board/basic/view_side.skin.php : 보기 사이드 영역의 UI를 개발합니다.

view_side.php에 보기 사이드 영역의 HTML을 이동시킵니다.
view_side.php에서 view_side.skin.php를 Include하도록 합니다.
view.skin.php에서 /bbs/view_side.php를 Include 합니다.

이제 준비 작업은 끝났습니다.

 

2. Metronic Admin 템플릿을 이용하여 UI 만들기

Metronic Admin Template의 TAB UI를 활용합니다.

HTML을 옮겨보고 상단 TAB의 수를 수정 후 화면을 살펴보겠습니다.

보기 사이드 영역의 HTML 작업이 끝난 후의 모습

 


3. 각 게시판의 최신글과 인기글을 돌려줄 쿼리 제작

mt703.lib.php에 get_board_list() 함수를 만듭니다.
파라메터는 게시판 ID, 최신/인기 선택자, 리스트개수 정도면 될 듯 합니다.
이제 쿼리 작업을 진행합니다.
(인기순... 잘못 정했네요... 인기의 척도가 뭔지 정해야 하는 상황이 ㅡㅡ;;)

-- 최신순은 쉽네...
select * from g5_write_notice where wr_is_comment = 0 order by wr_datetime desc, wr_num desc;

-- 인기순... 아뇌... 추천순으로 할걸... 괜히 복잡해짐...
-- 추천(wr_good)은 10점, 비추(wr_nogood)은 -10점, 스크랩(wr_scrap)은 5점, 댓글(wr_comment)은 3점, 조회수(wr_hit)는 1점
-- 날짜 개념이 들어가야 할 것 같은데... 오래 된건 차감이 되어야 한다... 
-- 지난 날짜 수당 -10점. 추천만큼 차감하면 되지 않을까... 
select 
	wr_id, wr_subject, wr_good, wr_nogood, wr_comment,
    (select count(ms_id) FROM g5_scrap AS s WHERE s.bo_table = 'notice' AND s.wr_id = b.wr_id) AS scrap_cnt
from g5_write_notice AS b where wr_is_comment = 0;
-- 아래 쿼리가 인기순 쿼리로 사용될 것.
SELECT 
	ms.*, 
    (ms.wr_good*10 + ms.wr_nogood*(-10) + ms.past_day*(-10) + ms.wr_comment*3 + wr_hit) AS hot_score
FROM (
	select 
		b.*, TIMESTAMPDIFF(DAY, wr_datetime, curdate()) AS past_day,
        (select count(ms_id) FROM g5_scrap AS s WHERE s.bo_table = 'notice' AND s.wr_id = b.wr_id) AS scrap_cnt
from g5_write_notice AS b 
where wr_is_comment = 0
) AS ms
ORDER BY hot_score DESC;

이렇게 쿼리작업이 완료되었습니다.

 


4. 각 게시판의 최신 댓글과 인기 댓글을 돌려줄 함수 제작

함수는 latest() 함수를 복사하여 만들 생각입니다.
중간에 return을 retrun이라고 오타를 내고는 원인을 못찾아서 시간 좀 허비했네요 ㅠㅠ

// 테이블명, 게새글/댓글 구분, 정렬구분 등을 전달 받아 게시글의 리스트를 돌려줌.
// latest() 함수를 참고하여 만들었고, 스킨과 캐싱부분만 제외시켰음. by tank. at 200704.
function get_board_list( $bo_table, $br_gubun, $ord_gubun, $rows=5, $subject_len=40 ) {
    global $g5;

    $list = array();

    $tmp_write_table = $g5['write_prefix'] . $bo_table; // 게시판 테이블 전체이름

    if ( $ord_gubun == "NEW" ) {
        $sql = "SELECT * FROM {$tmp_write_table} WHERE wr_is_comment = {$br_gubun} AND wr_option != 'secret' ORDER BY wr_datetime desc, wr_num desc LIMIT 0, {$rows}";
    } else if ( $ord_gubun == "HOT" ) {
        $sql = "SELECT
                    ms.*, (ms.wr_good*10 + ms.wr_nogood*(-10) + ms.past_day*(-10) + ms.wr_comment*3 + wr_hit) AS hot_score
                FROM (
                    select
                        b.*, TIMESTAMPDIFF(DAY, wr_datetime, curdate()) AS past_day,
                        (select count(ms_id) FROM g5_scrap AS s WHERE s.bo_table = 'notice' AND s.wr_id = b.wr_id) AS scrap_cnt
                from {$tmp_write_table} AS b
                where wr_is_comment = {$br_gubun} AND wr_option != 'secret'
                ) AS ms
                ORDER BY hot_score DESC
                LIMIT 0, {$rows}";
    }

    $result = sql_query($sql);                                  //tLog($sql, $result);
    for ($i=0; $row = sql_fetch_array($result); $i++) {         //tLog("row", $row);
        try {
            unset($row['wr_password']);     //패스워드 저장 안함( 아예 삭제 )
        } catch (Exception $e) {
        }
        $row['wr_email'] = '';              //이메일 저장 안함
        if (strstr($row['wr_option'], 'secret')){           // 비밀글일 경우 내용, 링크, 파일 저장 안함
            $row['wr_content'] = $row['wr_link1'] = $row['wr_link2'] = '';
            $row['file'] = array('count'=>0);
        }
        $list[$i] = $row;
        $list[$i]['bo_table'] = $bo_table;
    }

    return $list;
}

 

 

5. /bbs/view_side.php 개발

이 파일의 역할은 단지 함수를 호출하고 특정 변수에 결과를 저장하는 역할입니다.
이후 view_side.skin.php 파일을 호출하면 그만이죠.

<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가

$new_list = get_board_list($bo_table, 0, "NEW");       //tLog("new_list", $new_list); //새글 리스트
$hot_list = get_board_list($bo_table, 0, "HOT");       //tLog("hot_list", $hot_list); //인기글 리스트

$new_rep_list = get_board_list($bo_table, 1, "NEW");   //tLog("new_rep_list", $new_rep_list); //새 댓글 리스트
$hot_rep_list = get_board_list($bo_table, 1, "HOT");   //tLog("hot_rep_list", $hot_rep_list); //인기 댓글 리스트

include_once($board_skin_path.'/view_side.skin.php');
?>

 

 


6. view_side.skin.php 개발

받아온 각 배열변수를 각 영역에 맞게 입력시켜주기만 하면 되겠네요.

<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가

include_once(G5_LIB_PATH.'/latest.lib.php');
?>

<div class="flex-row-auto offcanvas-mobile w-300px w-xxl-375px" id="kt_inbox_aside">
    <!--begin::Card-->
    <div class="card card-custom card-stretch border-radius border-secondary mb-5 h-auto">
        <!--begin::Body-->
        <div class="card-body px-5">


            <ul class="nav nav-tabs" id="myListTab" role="tablist">
                <li class="nav-item">
                    <a class="nav-link active" id="new-tab" data-toggle="tab" href="#new">
                        <span class="nav-icon">
                            <i class="flaticon2-rocket-1"></i>
                        </span>
                        <span class="nav-text">최신글</span>
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" id="hot-tab" data-toggle="tab" href="#hot" aria-controls="hot">
                        <span class="nav-icon">
                            <i class="flaticon2-layers-1"></i>
                        </span>
                        <span class="nav-text">인기글</span>
                    </a>
                </li>
            </ul>
            <div class="tab-content mt-5" id="myListTabContent">
                <div class="tab-pane fade show active" id="new" role="tabpanel" aria-labelledby="new-tab">
                    <?php for ( $i=0; $i<count($new_list); $i++ ) {  //tLog("i", $i); ?>
                        <!--begin::Item-->
                        <div class="border-bottom border-secondary mb-3">
                            <a href="<?php echo G5_BBS_URL ."/board.php?bo_table=". $new_list[$i]["bo_table"] ."&wr_id=". $new_list[$i]["wr_id"]; ?>" class="font-weight-normal text-dark-50 text-hover-primary font-size-lg">
                                <?php echo $new_list[$i]['wr_subject']; ?>
                            </a>
                        </div>
                        <!--end::Item-->
                    <?php } ?>
                    <?php if ( count($new_list)==0 ) { ?>
                    <!--begin::Item-->
                        <div class="border-bottom border-secondary mb-3">
                            <a href="javascript:;" class="font-weight-normal text-dark-50 text-hover-primary font-size-lg">최신글이 없습니다.</a>
                        </div>
                        <!--end::Item-->
                    <?php } ?>
                </div>
                <div class="tab-pane fade" id="hot" role="tabpanel" aria-labelledby="hot-tab">
                    <?php for ( $i=0; $i<count($hot_list); $i++ ) {  //tLog("i", $i); ?>
                        <!--begin::Item-->
                        <div class="border-bottom border-secondary mb-3">
                            <a href="<?php echo G5_BBS_URL ."/board.php?bo_table=". $hot_list[$i]["bo_table"] ."&wr_id=". $hot_list[$i]["wr_id"]; ?>" class="font-weight-normal text-dark-50 text-hover-primary font-size-lg">
                                <?php echo $hot_list[$i]['wr_subject']; ?>
                            </a>
                        </div>
                        <!--end::Item-->
                    <?php } ?>
                    <?php if ( count($hot_list)==0 ) { ?>
                    <!--begin::Item-->
                        <div class="border-bottom border-secondary mb-3">
                            <a href="javascript:;" class="font-weight-normal text-dark-50 text-hover-primary font-size-lg">인기글이 없습니다.</a>
                        </div>
                        <!--end::Item-->
                    <?php } ?>
                </div>
            </div>


        </div>
        <!--end::Body-->
    </div>
    <!--end::Card-->









    <!--begin::Card-->
    <div class="card card-custom card-stretch border-radius border-secondary mb-5 h-auto">
        <!--begin::Body-->
        <div class="card-body px-5">


            <ul class="nav nav-tabs" id="myReplyTab" role="tablist">
                <li class="nav-item">
                    <a class="nav-link active" id="newRep-tab" data-toggle="tab" href="#newRep">
                        <span class="nav-icon">
                            <i class="flaticon2-rocket-1"></i>
                        </span>
                        <span class="nav-text">최신 댓글</span>
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" id="hotRep-tab" data-toggle="tab" href="#hotRep" aria-controls="hotRep">
                        <span class="nav-icon">
                            <i class="flaticon2-layers-1"></i>
                        </span>
                        <span class="nav-text">인기 댓글</span>
                    </a>
                </li>
            </ul>
            <div class="tab-content mt-5" id="myReplyTabContent">
                <div class="tab-pane fade show active" id="newRep" role="tabpanel" aria-labelledby="newRep-tab">
                    <?php for ( $i=0; $i<count($new_rep_list); $i++ ) {  //tLog("i", $i); ?>
                        <!--begin::Item-->
                        <div class="border-bottom border-secondary mb-3">
                            <a href="<?php echo G5_BBS_URL ."/board.php?bo_table=". $new_rep_list[$i]["bo_table"] ."&wr_id=". $new_rep_list[$i]["wr_id"]; ?>" class="font-weight-normal text-dark-50 text-hover-primary font-size-lg">
                                <?php echo $new_rep_list[$i]['wr_content']; ?>
                            </a>
                        </div>
                        <!--end::Item-->
                    <?php } ?>
                    <?php if ( count($new_rep_list)==0 ) { ?>
                    <!--begin::Item-->
                        <div class="border-bottom border-secondary mb-3">
                            <a href="javascript:;" class="font-weight-normal text-dark-50 text-hover-primary font-size-lg">최신글이 없습니다.</a>
                        </div>
                        <!--end::Item-->
                    <?php } ?>
                </div>
                <div class="tab-pane fade" id="hotRep" role="tabpanel" aria-labelledby="hotRep-tab">
                    <?php for ( $i=0; $i<count($hot_rep_list); $i++ ) {  //tLog("i", $i); ?>
                        <!--begin::Item-->
                        <div class="border-bottom border-secondary mb-3">
                            <a href="<?php echo G5_BBS_URL ."/board.php?bo_table=". $hot_rep_list[$i]["bo_table"] ."&wr_id=". $hot_rep_list[$i]["wr_id"]; ?>" class="font-weight-normal text-dark-50 text-hover-primary font-size-lg">
                                <?php echo $hot_rep_list[$i]['wr_content']; ?>
                            </a>
                        </div>
                        <!--end::Item-->
                    <?php } ?>
                    <?php if ( count($hot_rep_list)==0 ) { ?>
                    <!--begin::Item-->
                        <div class="border-bottom border-secondary mb-3">
                            <a href="javascript:;" class="font-weight-normal text-dark-50 text-hover-primary font-size-lg">인기글이 없습니다.</a>
                        </div>
                        <!--end::Item-->
                    <?php } ?>
                </div>
            </div>


        </div>
        <!--end::Body-->
    </div>
    <!--end::Card-->
</div>

 

 

이렇게 게시글 보기 페이지의 사이드 영역 작업이 완료되었습니다.

완료된 게시글 보기 우측의 사이드 영역



빨리 끝낼 수 도 있었을텐데...
작은 오타 실수로 인하여 시간을 많이 허비했네요.
위에서 말했던 return을 retrun으로...
좀 전에는 for(i=0; i<count... 구문을 for(i==0; i<count... 으로...
잘 나오던 리스트들이 갑자기 안나와서 굉장히 당황했었네요.

이렇게 게시판에 대한 모든 작업이 완료되었습니다.

다음 작업은 지금까지 한 일반 게시판 작업을 바탕으로 
갤러리 게시판 작업을 진행하도록 하겠습니다.

 

--------------------

우측 영역을 따라다니도록 추가로 작업했어요.
그런데... 특정 영역에서 멈추지가 않네요 ㅠㅠ

<script>
$("document").ready(function() {

    $(window).scroll(function()
    {
        $('.viewSideScroll').animate({top:$(window).scrollTop()+"px" },{queue: false, duration: 350});
    });

    $('.viewSideScroll').click(function()
    {
        $('.viewSideScroll').animate({ top:"+=15px",opacity:0 }, "slow");
    })

});
</script>

스크롤을 따라다니는 우측 영역

댓글2

  • Favicon of https://wsgvet.tistory.com BlogIcon 우성군 2020.07.12 02:39 신고

    최신글 인기글 최신댓글 인기댓글 모두 좋아요!

    한가지 걱정되는 부분은 페이지가 새로고침 될때마다 쿼리를 돌리면 서버에 부하가 가지 않을까요?

    그래서 최신글에 캐싱을 하는 것 같은 느낌이 듭니다!

    ㅎㅎ
    답글

    • 엇.. 23記가 올라가 있었네요 ㅎㅎ
      캐싱이라... 잠깐 생각하다가...
      저 정도로 무슨 별 일 있겠어라고 생각했지만... 쿼리가 그리 느리지 않더라구요. (혹시나 글이 엄청 많아지면 그때 고민해도... 쿨럭...)