이온디 유한회사 Since 2000.

-오픈XE마켓/워드프레스사이트제작의뢰/홈페이지만들기/홈페이지제작/홈페이지관리/서버관리/쇼핑몰제작/카페24/고도몰/퍼스트몰/shopify/아임웹/제로보드/XE제작분야 1위/로고제작/명함인쇄/고급명함제작/국내최다홈페이지제작전문기업.

메뉴 건너뛰기

메뉴 바로가기 본문으로 바로가기

개발팁

XE 댓글 평점 리뷰 기능 만들기 (랭킹 게시판)

2018.11.13 조회 112 댓글 0 추천 0

댓글에서 평점을 입력받아 글보기 화면과 글 리스트 화면에 해당 점수 평점을 출력하는 게시판을 만들어보겠습니다.

본 팁은 댓글의 추천수를 활용하여 게시글의 평점을 매기는 시스템입니다.

고로, 댓글 자체의 추천 시스템은 활용할 수가 없습니다.

댓글 자체에 좋아요, 싫어요를 할 수 있는 voted_count와 blamed_count 컬럼 중 voted_count를 사용하기 때문에 그렇습니다.

그 밖에 활용할만한 카운트 컬럼이 없더군요 ㅠ

해당 팁은 기존 board 모듈의 콘트롤러를 수정하고 쿼리문을 추가하고 하는 식으로 개발된 팁입니다.

가능하신 분은 별도 모듈을 개발하셔서 댓글을 작성할 때 해당 모듈로 해당 함수를 호출하는 식으로 개발하시면 될듯합니다.

※ document.getDocumentList가 호출되는 시점에서 해당 모듈에 있는 함수로 트리거로 통해 바꿔치기 하는 식으로 개발하시면, 코어는 건드릴 필요없이 작업이 가능합니다.

아직 제 수준은 거기까지가 안되므로 ;ㅁ;


1. 수정할 파일목록

1) 댓글 쓰기

/modules/board/skins/sketchbook5_review/_comment_write.html

2) 글보기 파일

/modules/board/skins/sketchbook5_review/_read_review.html

3) 게시판 모듈 코멘트 쓰기 쿼리문

/modules/board/tpl/filter/insert_comment.xml

4) 게시판 모듈 콘트롤러 파일

/modules/board/board.controller.php

5) 

/modules/board/queries/insert_comment.xml

6) 

/modules/board/queries/plusPackageStar.xml

7) 

/modules/board/queries/voteAdd.xml

8) 

/modules/board/queries/voteRemove.xml

9) 

/modules/board/queries/voteSum.xml


_comment_write.html

<input type="hidden" name="star_point" value="" />
<ul class="starPoint">
   <li><input type="radio" name="grd" id="grd1"><label for="grd1"><span class="grd grd1">1</span></label></li>
   <li><input type="radio" name="grd" id="grd2"><label for="grd2"><span class="grd grd2">2</span></label></li>
   <li><input type="radio" name="grd" id="grd3"><label for="grd3"><span class="grd grd3">3</span></label></li>
   <li><input type="radio" name="grd" id="grd4"><label for="grd4"><span class="grd grd4">4</span></label></li>
   <li><input type="radio" name="grd" id="grd5"><label for="grd5"><span class="grd grd5">5</span></label></li>
</ul>

코멘트 작성 form 안에 위 코드를 추가합니다.


_read_review.html

_read.html 파일에 인클루드되는 파일입니다. 

{@
$mi->tmb_effect='N';
if(!$mi->rd_tl_font) $mi->rd_tl_font='ngeb';
if(!$mi->rd_top_font) $mi->rd_top_font='ngeb';
if(!$mi->rd_btm_font) $mi->rd_btm_font='ngeb';
if(!$mi->prev_next_cut_size) $mi->prev_next_cut_size=60;
$sns_link=$oDocument->getPermanentUrl().'?l='.$lang_type;
$sns_title=urlencode($oDocument->getTitle());
}
<include target="_read_cat.html" cond="$mi->default_style=='review'"/>
<div class="lst_sort">
   <a class="sort1" href="{getUrl('mid',$mid,'order_type','','sort_index','','document_srl','')}">인기</a>
   <a class="sort2" href="{getUrl('mid',$mid,'order_type','desc','sort_index','regdate','document_srl','')}">신규등록</a>
   <a class="sort3" href="?mid={$mid}&order_type=desc&sort_index=regdate&act=dispBoardTagList">브랜드별</a>
   <div class="cat_m">카테고리별</div>
</div>
<div class="rd<!--@if(!$mi->rd_nav_style)--> rd_nav_style2<!--@end--><!--@if($mi->default_style=='blog')--> rd_blog {$mi->blog_style}<!--@end--> clear" style="padding:{$mi->rd_padding};" data-docSrl="{$oDocument->document_srl}">
   <!--// Header -->
   <div class="rd_hd clear">
      <!--브랜드명 이미지-->
      <div class="brand">
         <include target="./assets/brand.html" />
      </div>

      <!--이미지 썸네일-->
      <div class="thumb">
         <block loop="$oDocument->getUploadedFiles()=>$key,$file">
            <!--@if($key==0)-->
            <block cond="!$mi->img_insert2">
               {@
               $ext=substr($file->source_filename, -4);
               $ext=strtolower($ext);
               $extImg=in_array($ext,array('.jpg','jpeg','.gif','.png'));
               }
            </block>
            <block cond="$mi->img_insert2">
               {@
               $ext=substr($file->source_filename, -15);
               $ext=strtolower($ext);
               $extImg=in_array($ext,array('_rd_gallery.jpg','rd_gallery.jpeg','_rd_gallery.gif','_rd_gallery.png'));
               }
            </block>
            <img cond="$extImg" src="{$file->uploaded_filename}" alt="" />
            <!--@end-->
         </block>
      </div>
      <!--브랜드명 태그 -->
      {@ $tag_list=$oDocument->get('tag_list') }
      <div class="info_brandname">{$tag_list[0]}</div>

      <!--제목-->
      <div class="title">{$oDocument->getTitle()}</div>
      <!--별점-->
      
      {@
      //별점포인트
      $star_point = $oDocument->get('voted_count')/$oDocument->getCommentcount();
      $star_point_format = number_format((float)$star_point, 2, '.', '');

      //별점퍼센트
      $starRating = $oDocument->get('voted_count')*10*2/$oDocument->getCommentcount();

      }
      <div class="starbox">
         <div class="star_rating"><span style="width:{$starRating}%"></span></div>
         <div class="star_point">{$star_point_format}점</div>
         <div class="star_comment">({$oDocument->getCommentcount()}명)</div>
      </div>
      <!--카테고리-->
      <div class="cat">{$category_list[$oDocument->get('category_srl')]->title}부문</div>
      <!--제품정보(사용자정의)-->
      <block loop="$oDocument->getExtraVars() => $key,$val">
         <span class="info_size" cond="$val->eid=='info_size'">{$val->getValueHTML()}</span>
      </block>
      / <block loop="$oDocument->getExtraVars() => $key,$val">
         <span class="info_size" cond="$val->eid=='info_price'">{$val->getValueHTML()}</span>
      </block>
   </div>
   <!--// Body -->
   <div class="rd_body clear">
      <article>{$oDocument->getContent(false)}</article>
      <!--최저가 바로가기(사용자정의)-->
      <block loop="$oDocument->getExtraVars() => $key,$val">
         <div class="info_link" cond="$val->eid=='info_link' && $val->getValueHTML()">
            <a href="{$val->getValueHTML()}" target="_blank">최저가 바로가기</a>
         </div>
      </block>
   </div>

   <!--// Footer -->
   <div class="rd_ft">
      <div class="starbox">
         <div class="star_point">{$star_point_format}점</div>
         <div class="star_comment">({$oDocument->getCommentcount()}명 평가)</div>
         <div class="star_rating">
            <span style="width:{$starRating}%"></span>
         </div>
      </div>
      <div class="graph_wrap">
         {@
         $oDB = &DB::getInstance();
         $query = $oDB->_query('select * from xe_member_message where receiver_srl = '.$logged_info->member_srl.' AND message_type = "R" ORDER BY  regdate DESC limit 0, 5');
         $result = $oDB->_fetch($query);

         $oMemberModel =& getModel('member');
         $member_info = $oMemberModel->getMemberInfoByMemberSrl($val->sender_srl);
         }

         {@
         $oDB = &DB::getInstance();
         $query5 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 5');
         $result5 = $oDB->_fetch($query5);

         $query4 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 4');
         $result4 = $oDB->_fetch($query4);

         $query3 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 3');
         $result3 = $oDB->_fetch($query3);

         $query2 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 2');
         $result2 = $oDB->_fetch($query2);

         $query1 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 1');
         $result1 = $oDB->_fetch($query1);


         }
         <div class="review_box">
            <canvas id="chart-1"></canvas>
         </div>

         <script src="./assets/Chart.bundle.js"></script>
         <script src="./assets/utils.js"></script>
         <load target="js/chart.js" type="body" />
         <script>
            var presets = window.chartColors;
            var utils = Samples.utils;

            var options = {
               maintainAspectRatio: false,
               spanGaps: false,
               elements: {
                  line: {
                     tension: 0.100001
                  }
               },
               plugins: {
                  filler: {
                     propagate: false
                  }
               },
               scales: {

                  xAxes: [{

                     // x 텍스트
                     display: true,
                     ticks: {
                        autoSkip: false,
                        maxRotation: 0
                     },
                     //x 가이드라인
                     gridLines: {
                        display:false
                     }
                  }],
                  yAxes: [{

                     // y 텍스트
                     display: true,
                     // y가이드라인
                     gridLines: {
                        display:true
                     }
                  }]
               }
            };
            [false, 'origin', 'start', 'end'].forEach(function(boundary, index) {

               new Chart('chart-' + index, {
                  type: 'line',
                  data: {
                     //labels : ["최악","별로","쏘쏘","굿굿","짱짱"],
                     labels : ["","","","",""],
                     datasets: [{
                        backgroundColor: utils.transparentize(presets.red),
                        borderColor: presets.red,
                        //data : [2,6,9,26,45],
                        data : [{$result1->cnt},{$result2->cnt},{$result3->cnt},{$result4->cnt},{$result5->cnt}],
                        label: '',
                        fill: boundary
                     }]
                  },
                  options: utils.merge(options, {
                     title: {
                        text: '',
                        display: true
                     },
                     //responsive: true,
                     // 타이틀
                     legend: {
                        display: false
                     }

                  })
               });
            });
         </script>
      </div>

   </div>
   <!--// Read Footer Navi -->
   <div class="rd_ft_nav clear">
      <a cond="$mi->default_style!='viewer' && $mi->rd_ft_nav" class="btn_img fl" href="{getUrl('document_srl','')}"><i class="fa fa-bars"></i> {$lang->cmd_list}</a>
      <!--// SNS small -->
      <include cond="!$mi->to_sns" target="_read_sns.html" />
      <!--// Read Nav -->
      {@ $ft_read_nav=1}
      <include target="_read_nav.html" />
      {@ $ft_read_nav=''}
   </div>
   <!--// Comment -->
   <block cond="$mi->cmt_wrt=='sns'">
      {@
      $mi->cmt_wrt_position='';
      $mi->profile_img='';
      }
   </block>
   <div cond="!$mi->viewer_cmt" class="fdb_lst_wrp {$mi->fdb_style} {$mi->profile_img}">
      <div id="{$oDocument->document_srl}_comment" class="fdb_lst clear {$mi->fdb_nav} {$mi->cmt_wrt_position}">
         <!--// Editor -->
         <!--@if($mi->cmt_wrt=='sns')-->
         <!--// SocialXE -->
         <div cond="$oDocument->allowComment() && $mi->select_editor!='N'" class="editor_select bubble fr m_no" title="{$lang->noti_rfsh}">
            <a class="tg_btn2" href="#" data-href="#editor_select"><em class="fa fa-info-circle bd_info_icon"></em> {$lang->select_editor}</a>
            <div cond="$rd_idx==0" id="editor_select" class="editor_select_cnt tg_cnt2 wrp"><button type="button" class="tg_blur2"></button>
               <a class="on"|cond="$mi->cmt_wrt=='simple'" href="#" onclick="jQuery.cookie('bd_editor','simple');location.reload();return false"><em>✔ </em>{$lang->textarea}</a>
               <a class="on"|cond="$mi->cmt_wrt=='editor'" href="#" onclick="jQuery.cookie('bd_editor','editor');location.reload();return false"><em>✔ </em>{$lang->wysiwyg}</a>
               <a class="on"|cond="$mi->cmt_wrt=='sns'" href="#" onclick="jQuery.cookie('bd_editor','sns');location.reload();return false"><em>✔ </em>{$lang->sxc_editor}</a>
               <i class="edge"></i><button type="button" class="tg_blur2"></button>
               <!--// ie8; --><i class="ie8_only bl"></i><i class="ie8_only br"></i>
            </div>
         </div>
         <img class="zbxe_widget_output" widget="socialxe_comment" skin="sketchbook5" colorset="{$mi->colorset}" document_srl="{$oDocument->document_srl}" content_link="{getFullUrl('','document_srl',$oDocument->document_srl,'dummy','1')}" content_title="{htmlspecialchars($oDocument->getTitleText())}" enter_send="N" auto_view_sub="Y"|cond="!$mi->auto_view_sub" style="overflow:visible" />
         <!--@else-->
         <!--// Comment Write : Top -->
         <include cond="$oDocument->allowComment() && !$mi->cmt_wrt_position" target="_comment_write.html" />
         <!--// Comment List -->
         <div id="cmtPosition" aria-live="polite"><include target="_comment.html" /></div>
         <!--// Comment Write : Bottom -->
         <include cond="$oDocument->allowComment() && $mi->cmt_wrt_position=='cmt_wrt_btm'" target="_comment_write.html" />
         <!--@end-->
      </div>
   </div>
</div>

<!--// 목록 보이지 않을 때 보이는 하단 메뉴 -->
<div cond="$mi->rd_lst && $mi->default_style!='blog'" class="btm_mn clear" style="border-top:1px solid #CCC">
   <div class="fl">
      <a class="btn_img" href="{getUrl('document_srl','')}"><i class="fa fa-bars"></i> {$lang->cmd_list}</a>
   </div>
</div>

<hr id="rd_end_{$oDocument->document_srl}" class="rd_end clear" />



insert_comment.xml

<filter name="insert_comment" module="board" act="procBoardInsertComment">
  <form>
    <node target="star_point" required="true" />
    <node target="document_srl" required="true" />
    <node target="nick_name" required="true" maxlength="20"/>
    <node target="password" required="true" />
    <node target="email_address" maxlength="250" filter="email" />
    <node target="homepage" maxlength="250" filter="url" />
    <node target="content" required="true" minlength="1" />
  </form>
  <parameter>
    <param name="mid" target="mid" />
    <param name="document_srl" target="document_srl" />
    <param name="comment_srl" target="comment_srl" />
    <param name="parent_srl" target="parent_srl" />
    <param name="nick_name" target="nick_name" />
    <param name="password" target="password" />
    <param name="email_address" target="email_address" />
    <param name="homepage" target="homepage" />
    <param name="content" target="content" />
    <param name="is_secret" target="is_secret" />
    <param name="notify_message" target="notify_message" />
    <param name="star_point" target="star_point" />
  </parameter>
  <response callback_func="completeInsertComment">
    <tag name="error" />
    <tag name="message" />
    <tag name="mid" />
    <tag name="document_srl" />
    <tag name="comment_srl" />
  </response>
</filter>

코멘트를 작성할 때 star_point를 추가해주는 파일입니다.

<node target="star_point" required="true" />
<param name="star_point" target="star_point" />

기본 inset_comment.xml 에서 이 부분만 추가되었습니다.


board.controller.php

게시판 모듈 콘트롤러 파일입니다.

코멘트를 작성할 때도 동작하는 파일입니다.

334번째 줄에 다음과 같은 구문을 찾아주세요.

if($comment->comment_srl != $obj->comment_srl) {

...

}

오른쪽 처럼 수정하시면 됩니다.

336줄

$obj->voted_count = $obj->star_point;

349줄

$obj->voted_count = $obj->star_point;

369줄

$star_obj->module_srl = $this->module_srl;

        $star_obj->document_srl = $obj->document_srl;

        $star_obj->voted_count = $oDocument->get('voted_count')+$obj->star_point;

        $output = executeQuery('board.voteAdd', $star_obj);

        //$star_args->package_srl = $args->package_srl;

        //$star_args->voted = $package->voted+$args->star_point;

        //$output = executeQuery('resource.plusPackageStar', $star_args);

        //$output = executeQuery('document.procDocumentVoteUp', $star_obj);

        // $document_srl = Context::get('target_srl');

        // $oDocumentModel = getModel('document');

//        $oDocumentController = getController('document');

//        $document_srl = Context::get('document_srl');

//        return $oDocumentController->updateVotedCount($document_srl);


board.controller.php에서 코멘트 삭제시 차감하는 코드도 추가해야합니다.

function procBoardDeleteComment() 부분을 찾아서 반드시 그 바로 아래 첫번째줄에 작성해야합니다.

// 댓글 삭제 시 게시물 추천수 차감하기

        $obj = Context::getRequestVars();

        $obj->module_srl = $this->module_srl;



        $document_srl = Context::get('document_srl');

        $oDocumentModel = &getModel('document');

        $oDocument  = $oDocumentModel->getDocument($document_srl);


        $comment_srl    = Context::get('comment_srl');

        $oCommentModel = getModel('comment');

        $oComment = $oCommentModel->getComment($comment_srl, FALSE, FALSE);



        $star_obj->module_srl = $this->module_srl;

        $star_obj->document_srl = $obj->document_srl;

        $star_obj->voted_count = $oDocument->get('voted_count')-$oComment->get('voted_count');

        $output = executeQuery('board.voteAdd', $star_obj);



<스크린샷>

1) 평점+댓글쓰기 화면



2) 리스트 화면

- 글정렬 순서를 추천수+내림정렬로 하면 됩니다.


이 글이 마음에 드셨나요?지인과 공유해보세요.

이온디

이온디 홈페이지는 간결하며,

 손쉽게 수정할 수 있습니다.

댓글0
번호 제목 조회 추천 날짜
공지 [라이믹스] Another XE, 라이믹스 소개/설치하기 10 0 2019.01.09
공지 [XE소식] XE제작문의는 이온디 제작의뢰로 가주세요. 7 0 2018.12.10
공지 [사이트맵] XE/라이믹스 사이트맵 불편 기능을 알려주세요. 33 0 2017.09.23
329 [개발팁] [누리고]결제방법 없을 경우 체크하는 방법 13 0 2018.11.21
328 [자유게시판] 콘텐츠판 모듈의 검색 12 0 2018.11.19
[개발팁] XE 댓글 평점 리뷰 기능 만들기 (랭킹 게시판) 112 0 2018.11.13
326 [사용팁] XE 댓글 한번만 1회만 제한 40 0 2018.11.11
325 [자유게시판] 포인트 충전 모듈에서 kakaopay 결제방법 추가하기 806 0 2018.09.08
324 [궁금한점] xe js, css minifying 140 0 2018.08.27
323 [사용팁] [라이믹스] AJAX communication error while requesting admin.procAdminRecompileCacheFile 오류 200 0 2018.08.01
322 [추천자료] 누리고 푸시앱 58 0 2018.07.26
321 [자유게시판] XE 문자메세지 알림 설치하기 37 0 2018.07.25
320 [자유게시판] 부운영자 모듈 24 0 2018.07.25
319 [추천자료] XE 개발자센터 모듈 v.0.4.5 26 0 2018.07.25
318 [문제점] XE 보안 취약점 0 0 2018.07.25
317 [개발팁] [XE레이아웃] 하나의 레이아웃에서 act에 따라 다른 코드 출력하기 219 0 2018.05.27
316 [사용팁] XE 멀티 도메인 (2개 도메인) 사용하기 15 0 2018.05.27
315 [개발팁] [XE누리고] 2차 카테고리도 같이 출력하기 11 0 2018.05.16

상담신청

카카오채팅