Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Xe hack

2,673 views

Published on

XE 모듈함수들의 연계와 query

I. XE 내장함수 사용방법
II. 모듈간의 연결 – Trigger
III. 실시간반응 – exec_xml/json
IV. 쿼리사용 - $oDB = &DB::getInstance();

Published in: Internet
  • Be the first to comment

Xe hack

  1. 1. Sejin7940 (http://sejin7940.co.kr)
  2. 2.  I. XE 내장함수 사용방법  II. 모듈간의 연결 – Trigger  III. 실시간반응 – exec_xml/json  IV. 쿼리사용 - $oDB = &DB::getInstance();
  3. 3.  질문) 게시글에 글쓴이 회원정보들이 나타나게 하 고 싶은데 어떻게 하나요?  질문) 글을 추천한 추천인 목록을 스킨에 출력하려 면 어떻게 해야하나요?  질문) 어떤 기능을 구현하려면 어딜 어떻게 고쳐야 하나요? 해당 페이지 파일은 어디에?
  4. 4.  1. 함수 이름 규칙  1) Type + 모듈이름 + (Admin) + 고유이름  ( disp 는 view , proc 는 controller, get 은 model 파일에 있음.)  2) view 파일들은 해당 함수에 setTemplateFile(‘파일명’) 에 정의됨 ( 스킨 또는 tpl 내에 파일명.html 형태)  (getModel 등은 config/func.inc.php 에 정의되어있기에 XE 어디서나 사용가능)
  5. 5.  2. action 미리 선언 - module.xml 미리 정의  1) Url로 Act 변수를 직접 사용 – 주로 view 관련 disp action ( 회원가입-dispMemberSignUpForm)  2) exec_xml 나 exec_json 등에서 사용하려는 경우  - 행위 반응 proc action ( procDocumentVoteUp )  - 목록 추출 disp action ( dispBoardContentList )  3) 각 모듈의 module.xml 에 정의를 해줘야 인식됨  <action name="dispMemberInfo" type="view“> (참고) index="true“ 는 해당 모듈에서 별도의 act 없을때 기본 실행함수  admin_index=“true” 는 관리자화면에서 기본act
  6. 6.  3. 필요한 함수를 바로 선언해서 사용  1) getModel(‘모듈’)->함수, getController(‘모듈’)–>함수  getView(‘모듈’)->함수 형태로 사용  2) 함수별로 전달해야하는 변수값을 확인하고 받는 리턴값을 확인해서 사용  3) 함수들은 모듈, 애드온, 위젯뿐만 아니라,  레이아웃이나 스킨 등에서도 자유롭게 사용이 가능.  (스킨소스를 최대한 간편하게 하기 위해 모듈 내부에서 미리 선언해 변수 화한것 뿐)
  7. 7.  4. 예) 게시판 스킨 view 에서, 작성자 정보 출력  {@  $oMemberModel = getModel('member');  $writer_info = $oMemberModel- >getMemberInfoByMemeberSrl($oDocument- >getMemberSrl());  }  닉네임 : {$oDocument->getNickName()} <br/>  이름 : {$oDocument->getUserName()} <br/>  연락처 : {str_replace('|@|','-',$writer_info->tel)} <br/>  주소 : {str_replace('|@|',' ',$writer_info->address)}
  8. 8.  5. 참고) $oDocument, $oComment  $oDocument 는 document_srl 값을 기준으로 글정보를 함 수화한 변수  $oDocument = $oDocumentModel- >getDocument($document_srl); 로 구해진 거고  이를 통해 사용가능한 함수들은 document.item.php 파일에 정의되어있다.  댓글도 마찬가지로  $oComment = $oCommentModel- >getComment($comment_srl); 형태로 구현되어있고  comment.item.php 파일에 정의되어있다.
  9. 9.  질문) 내 회원정보를 보면 본 사람의 정보가 기록 되고 해당 글쓴이는 포인트가 차감되도록  질문) 글이 스크랩되면, 해당 글쓴이에게 포인트가 지급되게 하려면?  질문) 회원이 탈퇴하면 탈퇴내역을 남기고 해당 유 저가 쓴 모든 글들이 삭제되게 하려면?
  10. 10.  1. trigger 장점  1) 특정 함수의 실행 중간에 외부 다른 모듈의 함수를 실행가능  2) 함수 실행과정에서 변하는 변수 값들을 외부함수에  바로 전달가능  3) 손쉽게 원하는 위치에 trigger 를 추가 정의 가능  2. Trigger 선언  함수내부에 $trigger_output = ModuleHandler::triggerCall(' 모듈명.action', 'before/after', 전달할변수); 로 선언  (참고)Trigger 목록 - http://xpressengine.com/22556075
  11. 11.  3. Trigger 사용 방법  DB 의 module_trigger 라는 table 에 저장이 되어야함  해당 모듈의 class.php 파일에서 등록  checkUpdate()함수에서 if(!$oModuleModel->getTrigger  (‘트리거위치 모듈.함수’,’현재모듈’,’type’, ‘연결함수', 'after/before')) return true; 로 확인하고  moduleUpdate() 함수에서 $oModuleController- >insertTrigger (‘트리거위치 모듈.함수’,’현재모듈’,’type’, ‘연결할함수', 'after/before'); 등록  모듈 내부에, 연결할 함수를 해당 type 에 만들어두면 연결 됨
  12. 12.  4. 주의) 전달할 변수형태가 trigger 마다 모두 다르기에 trigger 사용시 미리 확인을 해야함  글 추천후 실행되는 ModuleHandler::triggerCall('document.updateVotedCou nt', 'after', $obj); 에서는 $obj 변수형태로 member_srl, document_srl, before_point, after_point 등이 전달  글 읽은 후 실행되는 ModuleHandler::triggerCall('document.updateReadedCo unt', 'after', $oDocument); 에서는 $oDocument 가 전달. $oDocument->getMemberSrl() , $oDocument- >get('document_srl') 형태 등으로 사용
  13. 13.  활용예 1 ) 글 작성시 포인트 추가되는 과정  글작성하면 insertDocument 함수 끝부분에  $trigger_output = ModuleHandler::triggerCall('document.insertDocument', 'after', $obj); 를 통해 트리거를 호출하면  Point 모듈에, $oModuleController- >insertTrigger('document.insertDocument', 'point', 'controller', 'triggerInsertDocument', 'after'); 로 선언된 trigger 가 실행되어  Point.controller.php 의 triggerInsertDocument 함수가 실 행되면서, 해당 글 작성에 따른 포인트가 지급
  14. 14.  활용예 2)  ‘이 게시글을’ , ‘이 댓글을’, ‘닉네임 클릭시 회원 관련 팝 업’등도 전부 다 이 trigger 기반으로 구현되어있고, trigger 추가로 마이페이지 관리등이 가능  활용예 3 ) 인맥사이트 등에서 포인트 이용한 타인의 회원 정보를 확인기능 등에..  modules/member/member.view.php 의 dispMemberInfo 함수에 새로운 triggerCall 을 추가로 정 의 ( before 형태 )  이 trigger 를 이용할 함수를 하나 정의해서 회원정보 확인 위해 필요한 포인트가 있는지 여부 / 있으면 포인트 차감 / 해당 회원에게는 방문자수 추가 및 포인트지급
  15. 15.  질문) 버튼클릭으로 ‘진행중’인 카테고리값이나 확 장변수 값을 ‘진행완료’로 값을 변경하게 하려면?  질문) 첫번째 카테고리 를 선택하면 그 하위의 2 차 카테고리가 옆에 selectbox로 뜨게 하려면?  질문) 특정값을 text 에 기입시 중복되지는 실시간 으로 확인하게 하려면? (회원가입시 닉네임처럼)
  16. 16.  1. exec_json / exec_xml 장점  - 스킨이나 레이아웃에서 XE 함수들과 변수를 ajax 기반으로 구현 해 바로 반응하도록 구현 지원  - ajax 를 아예 몰라도 사용 가능
  17. 17.  2. 내장형– doCallModuleAction - exec_xml기반 ( script)  1) doCallModuleAction(module, action, target_srl) 형태  세변수를 전달 - target_srl, cur_mid, mid  exec_xml(module, action, params, completeCallModuleAction);  해당 대상(target_srl) 에 대해 특정module의 특정action 을 실행  2) 리턴으로 completeCallModuleAction(ret_obj) 실행  실행 성공시 reload(), 실패시 alert 하는 구조이다.  3) 추천/비추천,스크랩,신고기능등 특정 srl에 대한 특정 module의 action을 호출하는 함수 등에서 현재 사용중  (참고 : common/js/xe.js 에 정의되어있음)
  18. 18.  3. exec_xml ( Javascript 기반)  1) exec_xml('모듈명', '모듈action', params(전달할변수), 콜 백함수, responses(리턴변수), 리턴함수params, fo_obj);  2) 모듈action 은 해당 modules.xml 에 정의 필요  3) params 는 array 도 되고, json 형식으로 써도 무관. Params 를 action 에서 Context::get('변수명') 형태로 받음  4) responses 는 배열로 정의를 해두고 (미리 정의 안 해두면 사용불가), 해당 모듈action 에서, $this->add('콜백변수명', '콜백변수값'); 형태로 전달하면 콜백함수에서 사용가능  5) 콜백함수는, function callback(ret_obj) 형태로 정의해두 고, 앞서 받은 ret_obj['콜백변수'] 형태로 사용가능
  19. 19.  4. jQuery.exec_json ( jQuery 기반)  사용법이 조금 더 단순하고, exec_xml 은 브라우저에 따라 에러 나는 경우가 있어 exec_json 을 사용하는 추세  1) jQuery.exec_json(‘모듈명.action’,params,콜백함수,에러함수);  2) 모듈명과 action 을 한 항목에 한꺼번에 기재되는것이 차이 3) params 변수 전달은 json 형태를 따라야한다. (배열불가)  예) var params = {'target_srl':target_srl,'cur_mid':current_mid}; 4) 콜백함수에 전달할 response_tags 변수를 미리 정의하지 않 아도 된다는 점이 exec_xml 과 다른 상당히 편한 부분이다
  20. 20.  5. 콜백변수에 반환데이터  하나의 row 로 된 데이터 뿐만 아니라, 여러 row 된 값의 반환까 지도 전부 가능  1) 하나의 row 만 반환하는 경우 - executeQuery  $output = executeQuery('document.getDocument', $args);  $this->add("list", $output->data);  하나의 row 값만 전달한 경우에는, 콜백함수에서  function callback(ret_obj){  var list = ret_obj['list'];  alert(list.document_srl);  }
  21. 21.  2) 복수개의 row 를 전달 – executeQueryArray => item  $output = executeQueryArray('document.getDocumentList', $args);  $this->add("list", $output->data);  복수개의 row 를 전달시 XE는 자동으로 item라는 항목을 만듬  function callback(ret_obj){  var list = ret_obj['list'];  alert(list.item[0].document_srl);  alert(list.item[1].document_srl);  }
  22. 22.  아니면 전체를 for 문으로 돌려 사용할 수 있다  function callback(ret_obj){  var list = ret_obj['list'];  for (var i in list.item){ alert(i + ' => ' + list.item[i]['document_srl']); }  }  이를 활용하면, 선택에 따라 목록리스트 추가출력 ( 더보기) 이나 selectbox 연계 기능등을 구현할 수 있다.
  23. 23.  6. 예시) 추천버튼 클릭시 바로 추천수 반영되도록  <a onclick=“doCallModuleActionDocumentVote('document', 'procDocumentVoteUp',{$oDocument->document_srl},’5’)”>추천 <span class="num" id="document_voted_count">{$oDocument- >get('voted_count')}</span></a>  이 기능을 위해선 procDocumentVoteUp 함수를 조금 수정해야함  $point = 1; 대신 $point=Context::get(‘point’); 로 추천수 증가폭 설정  내부에서 실행되는 updateVotedCount 함수에 보면,  $output->add('voted_count', $obj->after_point); 로는 애드온에서  반응을 안 하고, 그밑에 $this->add('voted_count', $obj->after_point); 형태로 추가
  24. 24.  1) exec_xml 로 구현  function doCallModuleActionDocumentVote(module, action, target_srl, point) {  var params = new Array();  params['target_srl'] = target_srl; // 글번호 전달  params['cur_mid'] = current_mid; // 현재의 게시판  params[‘point'] = point; // 증가할 추천수 전달  var response_tags = ['error','message','voted_count']; // voted_count 받음  exec_xml(module, action, params, completeDocumentVote, response_tags);  }
  25. 25.  Voted_count 가 response_tags 에 정의가 미리 되어있기에 add 된 이 값을 completeDocumentVote 에 전달이 가능하다  function completeDocumentVote(ret_obj, response_tags) {  var error = ret_obj.error;  var message = ret_obj.message;  var voted_count = ret_obj.voted_count;  if(!isNaN(parseInt(voted_count))) {  alert(voted_count+'번째로 추천');  jQuery('#document_voted_count').html(voted_count);  }  }
  26. 26.  2) exec_josn 으로 구현시에는  function doCallModuleActionDocumentVote(module, action, target_srl, point) {  var params = {'target_srl':target_srl,'cur_mid':current_mid, ‘point ': point};  jQuery.exec_json(module+'.'+action, params, completeDocumentVote);  } 만으로도 구현이 가능하다 (Response_tags 변수가 아예 빠져있다.)
  27. 27.  질문) XE query xml 문법에서 지원 안 하는 query 를 쓰고 싶을때는 어떻게 하나요?
  28. 28.  1, xml query 실행 – executeQuery() / executeQueryArray()  executeQuery 는 하나의 row 값만 받기 위한 용도  executeQueryArray 는 여러 row 로 된 list 형태를 받기 위한 용도 ( 리턴값이 stdClass 이기에 foreach로 접근해야 한다 )  그러나 실제적으로는, 이와 무관하게 xml 내부에 <navigation>~</navigation> 부분이 있는지 여부에 따라 리턴 되는 구조가 달라진다.
  29. 29.  2. executeQueryArray 와 xml query 의 장점  1) XE 만의 xml 형식의 query 를 통해 여러 DB 기반에서 작동  2) 다른 모듈등에서도 query 를 재정의할 필요없이 빌려 사용 가능  3) list 같이 여러 row 를 받는 경우, 자동으로 페이지구조 변수 ( $page_navigation )까지 자동 생성  4) 사용은 executeQuery(‘모듈명.query파일’,$변수,$칼럼) 형태  위젯의 경우는 ‘widgets.위젯명.query파일’,  애드온은 ‘addons.애드온명.query파일’
  30. 30.  3. XE 의 DB 활용위한 xml 의 한계  1) 가변적인 query 를 XE query 로는 구현이 어려움 2) XE xml query 에서 지원하지 않는 query 구문들도 사용 가능 ( 예. LOWER(칼럼) / 복잡한 서브쿼리나 table join 등) 3) 테이블, 칼럼생성/변경 등 table 자체의 변화를 주는 구현 난해 4) XE Core 에 정의되어있는 DB Table 에 문자열 칼럼을 추가하 면, schema 파일에 추가 선언이 없으면 insert/update 가 안 되 는 문제 발생. Core update 문제  5) page_navigation 기능이 필요없는 경우에도 불필요한 총 갯수 구하는 query 가 실행됨. 속도 저하의 원인이 됨
  31. 31.  이를 보완하기 위해, $oDB 를 직접 사용  $oDB = &DB::getInstance();  ( classes/db/DB.class.php 에 정의)  $oDB->_query($query); // 쿼리 실행  ( class/db/DB.class.php )  $oDB->_fetch($query); // 쿼리 결과 mysql_fetch_object  ( class/db/DBMysql.class.php )
  32. 32.  4. $oDB 를 이용해 query 구현하는 방법  $oDB = &DB::getInstance();  $db_info = Context::getDBInfo();  $prefix = $db_info->master_db["db_table_prefix"];  $database = $db_info->master_db["db_database"];  $query = " SELECT ~~~ "; // 가변적 query  $query .= “ WHERE document_srl = ".$args->document_srl “;  $qyery .= “ORDER BY ~~~”;  $query_query = $oDB->_query($query);  $result_query = $oDB->_fetch($query);  추후 이 $reulst_query 를 foreach 나 loop 로 돌리면 출력이 가능
  33. 33.  5. oDB 기반에서 page_navigation 변수 생성 방법  $oDB의 한계가 executeQuery와 달리, total_count 가 없기에 $page_navagation 을 생성하지 않는다.  XE 에서 목록의 page_navigation 구조를 자동으로 만들어주는데, $oDB 에서도 이를 이용하면 된다.  $output->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count);  ( classes/page/PageHandler.class.php )  $total_count, $total_page 는 별도 query 로, $page 는 Context 로  현재페이지, $page_count 는 설정을 참고하거나 미리 정의
  34. 34.  우선 사용할 쿼리를 두개로 분리 한 후..  $query_total = $query; // 총 개수 구하기 위한 용도  $query_limit = $query." LIMIT ".($page-1)*$list_count.",".$list_count; // 실제 사용할 쿼리  그 후 페이징에 필요한 값들 따로 구한 뒤 page_navigation 부터 구현  $query_total = $oDB->_query($query_total);  $output_total = $oDB->_fetch($query_total);  $output->total_count = $total_count = count($output_total);  $output->total_page = $total_page = (int)($output- >total_count/$list_count)+1;  $output->page = $page;  $output->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count);
  35. 35.  그 후 실제 필요한 query 를 실행  $query_limit = $oDB->_query($query_limit);  $output_limit = $oDB->_fetch($query_limit); //실제 필요한 값  if(count($output_limit)==1) {  $no=1;  $output->data[$no] = $output_limit;  }  else {  foreach($output_limit as $key=>$val) {  $no = $total_count-(($page-1)*$list_count)-$key;  $output->data[$no] = $val;  }  }  return $output;
  36. 36.  이렇게 해서 $output 을 리턴하면 executeQueryArray 와 동일한 형태의 결과가 리턴되기에  $output->data  $output->page_navagation  return $output;  스킨등에서 기존에 쓰던 형식 그대로 호환되어 사용이 가능해진다.

×