XpressEngine에 관련 내용에 대해서 이야기 합니다.
글 수 193
제로보드 사이트에서 몇몇 분들이 소스를 공개해 달라고 하셔서 원리를 설명 드릴까 합니다.
근데 참 어려운게 페이지 원리 이전에 위젯의 원리부터 설명해야할 필요가 있다는게... ㅠㅠ
위젯 프로그램은 ./widgets 라는 폴더안에 들어가 있으며, 이곳에 있어야지 실행가능 합니다.
newest_document 스킨을 이용한 페이지 기능 설치 방법을 설명 드리겠습니다.
추가, 수정에 필요한 파일들(실행 순서대로 나열합니다.)
- info.xml -
xml용으로 된 정보 입력 방식입니다. 위의 page_count와 page_type이라는 정보를 받고
페이지 네비게이션 출력 여부나 출력 시 몇개 까지 출력할지 등을 정할 수 있도록 추가합니다.
- newest_document.class.php [중요] -
이것을 기준점으로 위쪽은 정보를 어떻게 DB로 보낼지 입력 받은걸 처리하는 과정이며,
아래쪽은 DB에서로 부터 나온 결과물을 어떻게 처리할지의 과정이라고 보시면 됩니다.
간단히 설명 들어갑니다.
info.xml로 부터 입력 받은 값들은 상단에 function proc($args) {} 선언으로 부터 넘어오게 됩니다.
$args에는 아까 입력했던 page_count나 page_type 등이 포함하여 많은 정보들이 넘어오게 됩니다.
넘어온 page_count에 값이 없으면 기본값을 생성하기 위해 위와 같은 처리를 해줍니다.
(넘어온 데이터를 굳이 $page_count로 불필요하게 만들어서 담는 이유는 DB처리 후에
페이지 계산을 위해서 필요하기 때문에 마 본인이 별도로 담아 놓은 것이니 큰 신경쓰지마시길 바랍니다.)
DB로 넘어가는 값이 아닌 skin과 함수상의 처리이기 때문에 $obj로 넘기지 않습니다.
페이지를 사용하기로 했다면 현재 주소에 페이지가 있는지 검사 후 없으면 기본값 1로 대처하도록 합니다.
(Context::get('변수')는 주소창에서 index.php?aaa=bbb&ccc=ddd 등의 매개변수의 값을 뽑아오는 방법 입니다.)
widgets.newest_document.getNewestDocuments 는
widgets/newest_document/getNewestDocuments.xml 의 정보를 불러오는 의미 입니다.
본격적으로 페이지 기능 구현을 위한 정보들을 뽑아 정리 합니다.
아까전에 $page_type으로 저장했던 info.xml에서 받아온 출력여부를 저장합니다.
(별도로 $widget_info로 저장한 이유는 skins파일에 한번에 모아서 정보를 보낼려고 하는 겁니다.)
$output_count에서의 결과물이 단일일(한줄) 경우에는 위와 같이 직접 그 값에 접근시키면 됩니다.
위에 DB로 넘기기전에 선언했던 방식인데 이곳에서도 선언하도록 했습니다.(페이지 계산을 위해)
전체 게시물수/현재 페이지 수 = 총 페이지번호가 나오겠지요.
변수는 0부터 시작하기 때문에 표현을 위해서 0이 나오면 1이 되도록 하나씩 더 합니다.
floor() 함수를 이용해서 혹시나 나오는 소수점을 제거 합니다.
페이지 갯수를 skin처리를 위해 넘깁니다.
($GLOBALS['변수'] 를 이용한 이유는 원래 제로XE에서 만들어져 있는 곳을 보면,
$this->변수로 써 처리 되어있는데 저는 이게 이상하게 못불러오더라고요. 위젯이라서 그런가??
아무튼, 그래서 어쩔 수 없이 저리 처리했으며 $GLOBALS로 들어간 변수는 처리할때만이 아니라
그 해당 페이지에서의 완전한 종결까지 누적되어야 하기 때문에 저렇게 사용하였습니다.)
- getNewestDocuments.xml -
페이지별로의 결과를 뽑기 위해서 아래의 내용을 추가합니다.
<navigation> 안에
<page_count var="page_count" default="10" />
<page var="page" default="1" />
를 추가해주세요.
- getNewestDocumentsCount.xml -
getNewestDocuments.xml 의 정보와는 다르게 전체 게시물 수를 구하기 위해
<column name="*" /> 을
<column name="count(*)" alias="count" /> 으로
<navigation> 에서 아래의 것을 제거합니다.
<list_count var="list_count" default="20" />
- list.html -
중요한 부분만 설명하겠습니다.
아까 넘겼던 전체 게시물 수, 전체 페이지 갯수, 현재 페이지, 출력될 페이지상의 번호 갯수 를 WD_getNextPage로 넘겨 처리 받아서 $page_view로 결과를 담습니다.
해당 함수에서 결과로 나오는 값은
이것들이며 $GLOBALS은 누적, 다른곳에서의 호출을 위해 사용하고 $page는 최초 페이지 번호(당연히 1이겠죠), 마지막 페이지 번호를 담습니다.
상하로 중복 출력을 위해서 항상 시작전 결과값 중에 $GLOBALS['wd_i'] 횟수가 남아있다면 이를 0으로 초기화 합니다.
이제 while 문을 써서 $page_no가 나올때까지 반복합니다.
한번 실행할때 마다 $GLOBALS['wd_i'] 증가와 함께 WD_getNextPage을 선언했을때의 페이지 관련 정보를 더해서 그 마지막 페이지 이상인지 이하인지를 계산해서 결과를 보냅니다.
여기서 전체페이지번호 수와 증가 페이지번호수를 비교, 마지막 페이지번호를 비교해서 while 계속을 진행할지 멈출지를 계산합니다.
근데 참 어려운게 페이지 원리 이전에 위젯의 원리부터 설명해야할 필요가 있다는게... ㅠㅠ
위젯 프로그램은 ./widgets 라는 폴더안에 들어가 있으며, 이곳에 있어야지 실행가능 합니다.
newest_document 스킨을 이용한 페이지 기능 설치 방법을 설명 드리겠습니다.
추가, 수정에 필요한 파일들(실행 순서대로 나열합니다.)
newest_document/conf/info.xml <- 입력을 받기 위한 입력창
: 관리자페이지에서 코드 실행하기전에 이곳으로부터 정보를 입력 받습니다.
newest_document/newest_document.class.php <- 입력 받은 정보를 처리
: 입력 받은 정보를 적절히 정리해서 DB로 부터 결과값들을 받고 스킨 처리를 하는 파일
newest_document/queries/getNewestDocuments.xml <- DB Query용 XML 파일
: $page 번호 값에 따라서 결과를 출럭하기 위해 <navigation>에 내용을 추가 해야 합니다.
newest_document/queries/getNewestDocumentsCount.xml <- DB Query용 XML 파일
: 결과값용 Query와 다르게 페이지 기능을 만들기 위해 하나의 Query를 더 해야합니다.
newest_document/skins/default/list.html <- DB로 부터의 결과를 이용하여 표현하는 스킨 파일
: 관리자페이지에서 코드 실행하기전에 이곳으로부터 정보를 입력 받습니다.
newest_document/newest_document.class.php <- 입력 받은 정보를 처리
: 입력 받은 정보를 적절히 정리해서 DB로 부터 결과값들을 받고 스킨 처리를 하는 파일
newest_document/queries/getNewestDocuments.xml <- DB Query용 XML 파일
: $page 번호 값에 따라서 결과를 출럭하기 위해 <navigation>에 내용을 추가 해야 합니다.
newest_document/queries/getNewestDocumentsCount.xml <- DB Query용 XML 파일
: 결과값용 Query와 다르게 페이지 기능을 만들기 위해 하나의 Query를 더 해야합니다.
newest_document/skins/default/list.html <- DB로 부터의 결과를 이용하여 표현하는 스킨 파일
- info.xml -
<var id="page_count"> <name xml:lang="ko">페이지 목록수</name> <type>text</type> <description xml:lang="ko">출력될 페이지의 수를 정하실 수 있습니다. (기본 5개)</description> </var> <var id="page_type"> <name xml:lang="ko">페이지 출력 여부</name> <type>select</type> <description xml:lang="ko">페이지를 출력할지 선택하세요.</description> <options> <name xml:lang="ko">N</name> <value></value> </options> <options> <name xml:lang="ko">Y</name> <value>Y</value> </options> </var>
xml용으로 된 정보 입력 방식입니다. 위의 page_count와 page_type이라는 정보를 받고
페이지 네비게이션 출력 여부나 출력 시 몇개 까지 출력할지 등을 정할 수 있도록 추가합니다.
- newest_document.class.php [중요] -
이 파일에서 거의 모든 기능을 하기 때문에 이곳에서의 진행내용을 이해하지 못하면 만들기 어렵습니다.
우선, 페이지 기능을 만들기 위해서는 약간의 산수가 필요합니다.
그리고 계산을 위한 값이 만들어져야 겠지요.
우선, 페이지 기능을 만들기 위해서는 약간의 산수가 필요합니다.
그리고 계산을 위한 값이 만들어져야 겠지요.
$output = executeQueryArray('widgets.newest_document.getNewestDocuments', $obj);
이것을 기준점으로 위쪽은 정보를 어떻게 DB로 보낼지 입력 받은걸 처리하는 과정이며,
아래쪽은 DB에서로 부터 나온 결과물을 어떻게 처리할지의 과정이라고 보시면 됩니다.
/* 페이지 네비게이션 기능 추가 */ // 페이지 목록 수 (1,2,3,4....) $page_count = $args->page_count; if(!$page_count) $page_count = 5; $obj->page_count = $page_count; // 페이지 출력 여부 $page_type = $args->page_type; // 페이지 번호 구하기 if($page_type=='Y') $obj->page = (Context::get('page'))? Context::get('page'): 1; /* 페이지 네비게이션 기능 추가 끝 */
간단히 설명 들어갑니다.
info.xml로 부터 입력 받은 값들은 상단에 function proc($args) {} 선언으로 부터 넘어오게 됩니다.
$args에는 아까 입력했던 page_count나 page_type 등이 포함하여 많은 정보들이 넘어오게 됩니다.
$page_count = $args->page_count; if(!$page_count) $page_count = 5; $obj->page_count = $page_count;
넘어온 page_count에 값이 없으면 기본값을 생성하기 위해 위와 같은 처리를 해줍니다.
(넘어온 데이터를 굳이 $page_count로 불필요하게 만들어서 담는 이유는 DB처리 후에
페이지 계산을 위해서 필요하기 때문에 마 본인이 별도로 담아 놓은 것이니 큰 신경쓰지마시길 바랍니다.)
$page_type = $args->page_type;
DB로 넘어가는 값이 아닌 skin과 함수상의 처리이기 때문에 $obj로 넘기지 않습니다.
if($page_type=='Y') $obj->page = (Context::get('page'))? Context::get('page'): 1;
페이지를 사용하기로 했다면 현재 주소에 페이지가 있는지 검사 후 없으면 기본값 1로 대처하도록 합니다.
(Context::get('변수')는 주소창에서 index.php?aaa=bbb&ccc=ddd 등의 매개변수의 값을 뽑아오는 방법 입니다.)
$output = executeQueryArray('widgets.newest_document.getNewestDocuments', $obj); $output_count = executeQueryArray('widgets.newest_document.getNewestDocumentsCount', $obj);
widgets.newest_document.getNewestDocuments 는
widgets/newest_document/getNewestDocuments.xml 의 정보를 불러오는 의미 입니다.
$output과 또 하나 $output_count 부분을 하나더 만들어서 페이지 계산을 위해
위젯의 결과물을 뽑으려고 하는 대상의 전체 게시물 수를 뽑습니다.
위젯의 결과물을 뽑으려고 하는 대상의 전체 게시물 수를 뽑습니다.
// 페이지용 Query에 오류가 생기면 그냥 무시 if(!$output_count->toBool()) return; /* 페이지 네비게이션 기능 추가 */ $widget_info->page_type = $page_type; $widget_info->total_count = $output_count->data[0]->count; // 전체 개시물 수 $widget_info->page = (!Context::get('page'))? 1:Context::get('page'); // 현재 페이지 // 총 페이지 수 $total_count = $widget_info->total_count/$list_count; if($widget_info->total_count%$list_count != 0) $total_count+=1; $widget_info->total_page = floor($total_count); // 총 페이지 수 $widget_info->page_count = $page_count; // 총 페이지 수 /* 페이지 네비게이션 기능 추가 끝 */
본격적으로 페이지 기능 구현을 위한 정보들을 뽑아 정리 합니다.
$widget_info->page_type = $page_type;
아까전에 $page_type으로 저장했던 info.xml에서 받아온 출력여부를 저장합니다.
(별도로 $widget_info로 저장한 이유는 skins파일에 한번에 모아서 정보를 보낼려고 하는 겁니다.)
$widget_info->total_count = $output_count->data[0]->count; // 전체 개시물 수
$output_count에서의 결과물이 단일일(한줄) 경우에는 위와 같이 직접 그 값에 접근시키면 됩니다.
$widget_info->page = (!Context::get('page'))? 1:Context::get('page'); // 현재 페이지
위에 DB로 넘기기전에 선언했던 방식인데 이곳에서도 선언하도록 했습니다.(페이지 계산을 위해)
페이지 기능 계산을 위해서는 총 게시물의 수, 한페이지당 출력 수, 페이지번호 수 등의 값이 필요합니다.
$total_count = $widget_info->total_count/$list_count;
전체 게시물수/현재 페이지 수 = 총 페이지번호가 나오겠지요.
if($widget_info->total_count%$list_count != 0) $total_count+=1;
변수는 0부터 시작하기 때문에 표현을 위해서 0이 나오면 1이 되도록 하나씩 더 합니다.
$widget_info->total_page = floor($total_count); // 총 페이지 수
floor() 함수를 이용해서 혹시나 나오는 소수점을 제거 합니다.
$widget_info->page_count = $page_count; // 총 페이지 수
페이지 갯수를 skin처리를 위해 넘깁니다.
다음은 skin파일에서 역으로 newest_document.class.php안의 함수를 호출하여 page 내용을 받아오기 위한 함수들 입니다.
/** * @brief 다음 페이지 요청 **/ function WD_getNextPage($total_count, $total_page, $cur_page, $page_count = 10) { $first_page = $cur_page - (int)($page_count/2); if($first_page<1) $first_page = 1; $last_page = $total_page; if($last_page>$total_page) $last_page = $total_page; if($total_page < $page_count) $page_count = $total_page; $GLOBALS['wd_total_page'] = $total_page; $GLOBALS['wd_first_page'] = $first_page; $GLOBALS['wd_page_count'] = $page_count; $GLOBALS['wd_last_page'] = $last_page; $page->first_page = $first_page; $page->last_page = $last_page; return $page; } function WD_getNextPage2() { $page = $GLOBALS['wd_first_page']+$GLOBALS['wd_i']++; if($GLOBALS['wd_i'] > $GLOBALS['wd_page_count'] || $page > $GLOBALS['wd_last_page']) $page = 0; return $page; } function WD_getNextClear() { $GLOBALS['wd_i'] = 0; }
($GLOBALS['변수'] 를 이용한 이유는 원래 제로XE에서 만들어져 있는 곳을 보면,
$this->변수로 써 처리 되어있는데 저는 이게 이상하게 못불러오더라고요. 위젯이라서 그런가??
아무튼, 그래서 어쩔 수 없이 저리 처리했으며 $GLOBALS로 들어간 변수는 처리할때만이 아니라
그 해당 페이지에서의 완전한 종결까지 누적되어야 하기 때문에 저렇게 사용하였습니다.)
- getNewestDocuments.xml -
<query id="getNewestDocuments" action="select"> <tables> <table name="documents" /> </tables> <columns> <column name="*" /> </columns> <conditions> <condition operation="in" column="module_srl" var="module_srl" filter="number" /> <condition operation="equal" column="category_srl" var="category_srl" pipe="and" /> </conditions> <navigation> <index var="sort_index" default="list_order" order="order_type" /> <list_count var="list_count" default="20" /> <page_count var="page_count" default="10" /> <page var="page" default="1" /> </navigation> </query>
페이지별로의 결과를 뽑기 위해서 아래의 내용을 추가합니다.
<navigation> 안에
<page_count var="page_count" default="10" />
<page var="page" default="1" />
를 추가해주세요.
- getNewestDocumentsCount.xml -
<query id="getNewestDocumentsCount" action="select"> <tables> <table name="documents" /> </tables> <columns> <column name="count(*)" alias="count" /> </columns> <conditions> <condition operation="in" column="module_srl" var="module_srl" filter="number" /> <condition operation="equal" column="category_srl" var="category_srl" pipe="and" /> </conditions> <navigation> <index var="sort_index" default="list_order" order="order_type" /> </navigation> </query>
getNewestDocuments.xml 의 정보와는 다르게 전체 게시물 수를 구하기 위해
<column name="*" /> 을
<column name="count(*)" alias="count" /> 으로
<navigation> 에서 아래의 것을 제거합니다.
<list_count var="list_count" default="20" />
- list.html -
<!--@if($widget_info->page_type=='Y')--> <!-- 페이지 네비게이션 --> <div class="pageNavigation"> <a href="{getUrl('page','','document_srl','','division',$division,'last_division',$last_division)}" class="goToFirst"> <img src="./images/common/bottomGotoFirst.gif" alt="{$lang->first_page}" width="7" height="5" /></a> <!-- 페이지 정보 구하기 위해 선언 --> {@$page_view = WD_getNextPage($widget_info->total_count,$widget_info->total_page,$widget_info->page,$widget_info->page_count)} <!-- 중복 페이지 정보 출력을 위해 사전 초기화 --> {@WD_getNextClear()} <!--@while($page_no = WD_getNextPage2())--> <!--@if($widget_info->page == $page_no)--> <span class="current">{$page_no}</span> <!--@else--> <span class="pageNavigations"><a href="{getUrl('page',$page_no,'document_srl','','division',$division,'last_division',$last_division)}" class="pageNavigation2">{$page_no}</a></span> <!--@end--> <!--@end--> <a href="{getUrl('page',$page_view->last_page,'document_srl','','division',$division,'last_division',$last_division)}" class="goToLast"> <img src="./images/common/bottomGotoLast.gif" alt="{$lang->last_page}" width="7" height="5" /></a> </div> <!--@end-->
중요한 부분만 설명하겠습니다.
{@$page_view = WD_getNextPage($widget_info->total_count,$widget_info->total_page,$widget_info->page,$widget_info->page_count)}
아까 넘겼던 전체 게시물 수, 전체 페이지 갯수, 현재 페이지, 출력될 페이지상의 번호 갯수 를 WD_getNextPage로 넘겨 처리 받아서 $page_view로 결과를 담습니다.
해당 함수에서 결과로 나오는 값은
$GLOBALS['wd_total_page'] = $total_page; $GLOBALS['wd_first_page'] = $first_page; $GLOBALS['wd_page_count'] = $page_count; $GLOBALS['wd_last_page'] = $last_page; $page->first_page = $first_page; $page->last_page = $last_page;
이것들이며 $GLOBALS은 누적, 다른곳에서의 호출을 위해 사용하고 $page는 최초 페이지 번호(당연히 1이겠죠), 마지막 페이지 번호를 담습니다.
{@WD_getNextClear()}
상하로 중복 출력을 위해서 항상 시작전 결과값 중에 $GLOBALS['wd_i'] 횟수가 남아있다면 이를 0으로 초기화 합니다.
<!--@while($page_no = WD_getNextPage2())--> <!--@if($widget_info->page == $page_no)--> <span class="current">{$page_no}</span> <!--@else--> <span class="pageNavigations"><a href="{getUrl('page',$page_no,'document_srl','','division',$division,'last_division',$last_division)}" class="pageNavigation2">{$page_no}</a></span> <!--@end--> <!--@end-->
이제 while 문을 써서 $page_no가 나올때까지 반복합니다.
function WD_getNextPage2() { $page = $GLOBALS['wd_first_page']+$GLOBALS['wd_i']++; if($GLOBALS['wd_i'] > $GLOBALS['wd_page_count'] || $page > $GLOBALS['wd_last_page']) $page = 0; return $page; }
한번 실행할때 마다 $GLOBALS['wd_i'] 증가와 함께 WD_getNextPage을 선언했을때의 페이지 관련 정보를 더해서 그 마지막 페이지 이상인지 이하인지를 계산해서 결과를 보냅니다.
여기서 전체페이지번호 수와 증가 페이지번호수를 비교, 마지막 페이지번호를 비교해서 while 계속을 진행할지 멈출지를 계산합니다.
이것을 포인트랭킹 위젯에 적용시켜서
예를들어 목록을 20개로 정해놓으면 첫 페이지는 1~20등,
다음 페이지를 선택하면 21~40등 이 나오게 하고 싶은데 어찌해야 할까요?
도움 부탁드릴게요.