웹마스터 팁
XE로 API 처리 완전 정복하기(2)
2009.11.03 14:23
XE로 API 처리 두번째
참고
첫번째 설명에 사용된 내용을 (1) 이라는 명칭으로 사용합니다.
목차
- board.api.php 흐름 이해
- FileHandler::getRemoteResource() 구조, header 선언
- blogapi 애드온으로 metaWeblog 글 입력하기
- api 처리용 심플 모듈 만들어보기
1. board.api.php 흐름 이해
<?php class boardAPI extends board { function dispBoardContentList(&$oModule) { $document_list = $this->arrangeContentList(Context::get('document_list')); $oModule->add('document_list',$document_list); $oModule->add('page_navigation',Context::get('page_navigation')); } ... ?>
- XE에서 json과 xml 형식으로 정보를 출력시키는 소스는 모듈.api.php에 위치합니다.
- api.php의 처리는 모듈의 conf/module.xml 정보에 action type이 view로 되어있는 act 이름을 대상으로 동작합니다.
- module.xml에 아래의 정보가 선언되어있을 경우
- (2010.12.04) 최근 버전에서는 conf/module.xml에 view, controller, model, api 의 값에 따라 각 class의 함수를 요청합니다.
- (2010.12.04) controller.php로 요청하는 함수에는 &$oModule와 같은 변수를 넘기지 않아 오류가 발생되니 주의가 필요합니다.
<action name="dispBoardContentList" type="view" />
- 보통의 경우는 http://사이트/?mid=board&act=dispBoardContentList 이런식으로의 접근을 하여
- view 라는 값을 얻고 board.view.php에 dispBoardContentList() 함수에 의해 처리 됩니다.
- api.php는 (1)에서 설명드린 정보 중 content_type이 application/xml 또는 application/json일 경우
board.view.php에 있는 dispBoardContentList()을 처리한 후 board.api.php의 dispBoardContentList()을 처리하게 됩니다.
boardAPI::dispBoardContentList(&$oModule) 소스를 설명하자면
- (1)의 정보 요청 시 대상 act를 접근하여 아래의 소스가 동작하게 되고
function dispBoardContentList(){ ...중략 // 일반 글을 구해서 context set $output = $oDocumentModel->getDocumentList($args, $this->except_notice); Context::set('document_list', $output->data); Context::set('total_count', $output->total_count); Context::set('total_page', $output->total_page); Context::set('page', $output->page); Context::set('page_navigation', $output->page_navigation); // 목록 설정값을 세팅 $oBoardModel = &getModel('board'); Context::set('list_config', $oBoardModel->getListConfig($this->module_info->module_srl)); }
- dispBoardContentList()에서는 Context::set('document_list', $output->data),Context::set('page_navigation', $output->page_navigation) 를 활용하여 $document_list 정보를 만든 후 $oModule->add()를 이용하여 json,xml 포맷으로 정보를 만들어 출력하게 됩니다.
2. FileHandler::getRemoteResource() 구조, header 선언
FileHandler::getRemoteResource($url, $body = null, $timeout = 3, $method = 'GET', $content_type = null, $headers = array(), $cookies = array(), $post_data = array())
return remote file's content via HTTP
매개변수:
[in] $url the address of the target file
[in] $body HTTP request body
[in] $timeout connection timeout
[in] $method GET/POST
[in] $content_type content type header of HTTP request
[in] $headers headers key vaule array.
[in] $cookies cookies key value array.
[in] $post_data request arguments array for POST method
FileHandler.class.php는 각종 파일 입출력 복사 등 데이터 처리에 대한 전반적인 기능들이 포함되어있기 때문에 활용하시면 큰 도움이 됩니다.
<?php $content = "<?xml version=\"1.0\" encoding=\"utf-8\" ?> <methodCall> <params> <mid><![CDATA[board]]></mid> <content><![CDATA[내용]]></content> <document_srl><![CDATA[]]></document_srl> <title><![CDATA[제목]]></title> <tags><![CDATA[태그]]></tags> <allow_comment><![CDATA[Y]]></allow_comment> <allow_trackback><![CDATA[Y]]></allow_trackback> <nick_name><![CDATA[라르게덴]]></nick_name> <password><![CDATA[1234]]></password> <email_address><![CDATA[]]></email_address> <homepage><![CDATA[]]></homepage> <act><![CDATA[procBoardInsertDocument]]></act> <module><![CDATA[board]]></module> </params> </methodCall>"; $header = sprintf( "POST /xe/index.php HTTP/1.1\r\n". "Host: 127.0.0.1 \r\n". "Content-Type: application/xml\r\n". "Content-Length: ".strlen($contents)."\r\n\r\n". "Connection: Close\r\n\r\n". $contents."\r\n"); $fp = @fsockopen("127.0.0.1", "80", $errno, $errstr, 5); if($fp){ fputs($fp, $header); fclose($fp); } ?>
- 상기와 같이 fsockopen()을 이용한 처리를 XE는 getRemoteResource()를 이용하여 데이터를 주고 받을 수 있게 처리해줍니다.
- 실제 해당 함수에는 xe의 libs 폴더의 PEAR.php, Request.php, Socket.php, URL.php 등 여러 라이브러리를 이용하여 처리되게 되어있습니다.
- (2010.12.04) fsockopen()를 이용한 처리에 오류가 있어 정정합니다.
$url
상기 내용을 보시면 도메인과 포트, url, 파일명까지 구분되어져 header 선언을 하고 있습니다.getRemoteResource()에서는 http://사이트:포트/경로/index.php를 전체를 입력시키고 있으며, 이는 URL.php를 통하여
부분별 연관배열로 파싱되어, 알맞은 헤더위치에 삽입되게 됩니다.
$body
상기 xml 포멧과 같은 목적지로 보낼 데이터를 말합니다.xml 형식과 같이 쓸 경우도 있으며 실제적으로는 http://사이트/?매개변수=1 등의 a=1&b=2&c=3 을 입력하여도 처리 됩니다.
$timeout
응답을 기다릴 제한시간$content_type
어떤 방식으로의 통신이냐에 따라서 정보의 처리가 달라지게 됩니다.application/x-www-form-urlencoded
a=1&b=2&c=3 와 같은 일반 적인 정보를 가지고 web에 표시되는 내용을 가져오거나 할때 사용합니다.
application/xml
xml 형식으로 정보를 주고 XE는 이를 다시 XML 형식으로 결과를 보내줍니다.
application/json
javascript에서 정보를 보내고 XE에서 json 형식으로 결과를 보내줍니다.
application/octet-stream
blogapi 애드온에 선언되어있는 metaWeblog.[act]을 이용하기 위해 상기와 같이 처리합니다.
첨부파일 저장 등의 동작도 겸할때 사용합니다.
$headers
기본 헤더 정보 이외의 별도의 헤더 정보를 추가할 때 사용합니다.User-Agent : PEAR HTTP_Request class
Connection : close
Authorization : Basic dHlhbWkY
Proxy-Authorization : Basic dHlhbWkY
Accept-Encoding : gzip
상기와 같은 내용들은 Request.php 안에서 선언되거나 활용되어 집니다. 별도의 값이 필요하다면
array( "me2_application_key"=>$this->application_key, "Authorization"=>"Basic ".base64_encode($this->user_id), )
상기 처럼 추가 헤더를 이용할 경우 사용됩니다.
$cookies
안써봐서 설명 불가$post_data
안써봐서 설명 불가
3. blogapi 애드온으로 metaWeblog 글 입력하기
대표적으로 글 조회, 입력, 첨부파일 3가지 메소드에 대해서만 쓰겠습니다.
(1) 단독형의 기본 선언 내용 설명은 제외합니다. (1) 설명과 같이 적용하시면 됩니다.
※ 해당 기능을 하기 전에 반드시 XE blogapi 애드온이 활성화되어있어야 합니다.(모듈 선택은 모두 해제) ※ $uri 주소는 api가 꼭 붙어야 하며 끝에 / 는 넣지 마십시오.
글 조회
<?php $uri = "http://도메인/xe/board/api"; $body = "<?xml version=\"1.0\" encoding=\"utf-8\"?> <methodCall> <methodName><![CDATA[metaWeblog.getPost]]></methodName> <params> <param><value><string><![CDATA[62]]></string></value></param> <param><value><string><![CDATA[admin]]></string></value></param> <param><value><string><![CDATA[1234]]></string></value></param> <param> <value> <boolean>1</boolean> </value> </param> </params> </methodCall>"; $buff = @FileHandler::getRemoteResource($uri, $body, 3, "POST", "application/octet-stream"); echo $buff; ?>
확인
<methodResponse> <params> <param> <value> <struct> <member><name>categories</name><value><array><data><value><![CDATA[]]></value></data></array></value></member> <member><name>dateCreated</name><value><dateTime.iso8601>20091103T11:37:10</dateTime.iso8601></value></member> <member><name>description</name><value><![CDATA[<!--BeforeDocument(62,4)--><div class="document_62_4 xe_content"><p> sadfsadfsaf</p></div><!--AfterDocument(62,4)-->]]></value></member> <member><name>link</name><value>http://211.234.236.218/xe/62</value></member> <member><name>postid</name><value><string>62</string></value></member> <member><name>title</name><value><![CDATA[asdfsadfsf]]></value></member> <member><name>publish</name><value><boolean>1</boolean></value></member> </struct> </value> </param> </params> </methodResponse>
이런 결과물이 출력된다면 성공입니다. 출력물은 (1)에도 설명했지만 알아서 파싱해서 활용하셔야겠지요.
글 입력
<?php $uri = "http://도메인/xe/board/api"; $body = "<?xml version=\"1.0\" encoding=\"utf-8\"?> <methodCall> <methodName>metaWeblog.newPost</methodName> <params> <param><value><string><![CDATA[board]]></string></value></param> <param><value><string><![CDATA[admin]]></string></value></param> <param><value><string><![CDATA[1234]]></string></value></param> <param><value><struct> <member><name><![CDATA[title]]></name><value><string><![CDATA[제목]]></string></value></member> <member><name><![CDATA[description]]></name><value><string><![CDATA[내용]]></string></value></member> <member><name><![CDATA[categories]]></name><value><array><data><value><string><![CDATA[135]]></string></value></data></array></value></member> <member><name><![CDATA[tagwords]]></name><value><array><data><value><string><![CDATA[태그,태그2]]></string></value></data></array></value></member> </struct></value></param> <param> <value> <boolean>1</boolean> </value> </param> </params> </methodCall>"; $buff = @FileHandler::getRemoteResource($uri, $body, 3, "POST", "application/octet-stream"); echo $buff; ?>확인
<?xml version="1.0" encoding="utf-8"?> <methodResponse><params><param> <value><string>71</string></value> </param></params> </methodResponse>
이런 내용이 나오면 성공입니다.
※ 카테고리의 경우 번호를 입력해야하는지 등록되어있는 실제 이름을 입력해야하는지는 확인 안해봐서 잘 모르겠네요.
첨부파일 등록
<?php $body = "<?xml version=\"1.0\" encoding=\"utf-8\"?> <methodCall> <methodName>metaWeblog.newMediaObject</methodName> <params> <param><value><string><![CDATA[board]]></string></value></param> <param><value><string><![CDATA[admin]]></string></value></param> <param><value><string><![CDATA[1234]]></string></value></param> <param><value><struct> <member><name><![CDATA[name]]></name><value><string><![CDATA[C:\abc.jpg]]></string></value></member> <member><name><![CDATA[type]]></name><value><string><![CDATA[image/jpeg]]></string></value></member> <member><name><![CDATA[bits]]></name><value><base64><![CDATA[".base64_encode(FileHandler::readFile("C:\abc.jpg")]."]></base64></value></member> </struct></value></param> </params> </methodCall>"; $buff = @FileHandler::getRemoteResource($uri, $body, 3, "POST", "application/octet-stream"); echo $buff; ?>확인
안해봐서 결과는 모르겠습니다.
- 첨부파일의 경우 글 등록을 하기 이전에 진행해야 합니다.
- 글 등록 시 첨부파일이 있다라고 가정한다면 첨부파일 업로드 이후 바로 글 등록 프로세스를 돌려야 합니다.
- 첨부파일이 먼저 등록되면 blogapi를 통하여 임시 저장소에 파일이 등록되고 글 등록시에 해당 임시경로의 파일을 전부 끌어다가 저장하고 파기하는 방법으로 구현되어있기 때문입니다.
4. api 처리용 모듈 만들어보기
모듈 작성 내용은 http://sol.textyle.kr/26153 를 참고해주시고 모듈 작성에 시간이 걸리기 때문에 첨부파일로 올려두겠습니다.
이 모듈의 목적은 모듈.api.php를 이용하여 기본조회, 모듈.model.php의 정보가공, 모듈.controller.php의 정보처리가 되게끔 설계해주는 내용입니다.
※ 이렇게까지 할 필요가 있나 하시겠지만 외부에서 반복적인 정보 수행이나 기계적인 정보처리를 위한 통신은 URL로 노출되어 처리 될 경우 쉽게 웹브라우저로 인위적 수행이 되기에 api를 이용하면 일반 웹처리 노출에서 자유로워지지 않을까해서 입니다.
모듈/conf/module.xml을 아래와 같이 만듭니다.
<?xml version="1.0" encoding="utf-8"?> <module> <grants /> <permissions /> <actions> <action name="dispContentView" type="view" index="true" /> </actions> </module>
모듈/모듈.class.php를 아래와 같이 만듭니다.
<?php class 모듈 extends ModuleObject { function moduleInstall() { } function checkUpdate() { return false; } function moduleUpdate() { return new Object(0, "success_updated"); } function recompileCache() { } } ?>
모듈/모듈.view.php를 아래와 같이 만듭니다.
<?php class 모듈View extends 모듈 { function init() { } function dispContentView() { } } ?>
- view에서 Context::set()에 처리 결과를 넣고 api로 활용할지 사용할 수 있습니다.
- 아무것도 할일 없다고 해서 함수를 없애면 api.php가 동작하지 않습니다. 껍데기라도 만드셔야 합니다.
<?php class 모듈Model extends 모듈 { function init() { } function _dispContentView($args) { $args->model = "모듈Model"; return $args; } } ?>
모듈/모듈.controller.php를 아래와 같이 만듭니다.
<?php class 모듈Controller extends 모듈 { function init() { } function _dispContentView($args) { $args->controller = "모듈Controller"; return $args; } } ?>
모듈/모듈.api.php를 아래와 같이 만듭니다.
<?php class 모듈API extends 모듈 { function dispContentView(&$oModule) { $args = Context::getRequestVars(); $oNmsModel = &getModel("nms"); $model = $oNmsModel->_dispContentView($args); $oNmsController = &getController("nms"); $controller = $oNmsController->_dispContentView($args); $oModule->add("model",$model->model); $oModule->add("controller",$controller->controller); } } ?>
- init()를 넣지마시길 바랍니다. '+
'extends 모듈'은 꼭 쓰셔야 합니다. - 넘겨받은 매개변수를 $args로 만들고 각 해당 클래스의 함수로 넘겨 데이터를 가공받습니다.
- 처리된 데이터를 $oModule->add()에 입력해주시면 json/xml 선언에 따라 포멧을 만들어 내보냅니다.
테스트
<?php // _XE_PATH_ 생성 define("_XE_PATH_", str_replace("api.php", "", str_replace("\\", "/", __FILE__))); // FileHandler(PEAR,Socket) 등을 사용하기 위해서 XE 정보를 선언 define("__ZBXE__", true); require_once(_XE_PATH_."config/config.inc.php"); $uri = "http://127.0.0.1/xe/"; $body = "<?xml version=\"1.0\" encoding=\"utf-8\" ?> <methodCall> <params> <module><![CDATA[모듈명]]></module> <act><![CDATA[dispContentView]]></act> </params> </methodCall>"; $buff = @FileHandler::getRemoteResource($uri, $body, 3, "POST", "application/xml"); echo $buff; ?>확인
<response> <error>0</error> <message>success</message> <model><![CDATA[모듈Model]]></model> <controller><![CDATA[모듈Controller]]></controller> </response>
참고자료
- 김기철980님의 [강추]!! 긁어와서 [자동]으로 게시글로!! [메타 블로그] php 로 넣기!!! xe블로그api를 이용한.. http://www.xpressengine.com/17686946- (1) 항목에 참고 자료
끝
허접하게나마 아는데로 적어봤습니다.
설명 중 미흡하거나 잘못 된 사항이 있을 수 있습니다.
참고용으로만 생각해주시고 동작이 안되면 열심히 자료 찾으셔서 공부해보시기 바랍니다.
셈플용 모듈이랑 자료는 좀 있다(어쩌면 내일) 올리겠습니다.
올린다는 자료가 늦어버렸습니다. 테스트 모듈을 올렸고 모듈안에 test.php 파일이 있습니다.
http://사이트/xe/modules/test_api/test.php 로 실행하시고 소스보기를 하시면 값이 출력 됩니다.
- [2017/03/15] 웹마스터 팁 다음 우편번호 5자리 적용 *1
- [2015/08/06] 묻고답하기 metaWeblog을 이용하여 게시판에 저장할때 _extra_vars 는 어떻게 하면 좋은지요.
- [2015/07/29] 묻고답하기 게시판DX 모바일환경에서 댓글 열람 불가
- [2015/06/05] 묻고답하기 스케치북 모바일 스킨 문의 *9
- [2015/02/25] 웹마스터 팁 kakao Javascript SDK logout
댓글 2
-
sol
2009.11.03 16:14
-
라르게덴
2009.11.03 16:39
그렇군요. controller만 시도해봐서 안되는 줄 알았는데 model과 view가 되는군요.
수정해놔야겠네요 ^^
제목 | 글쓴이 | 날짜 |
---|---|---|
갑자기 관리자 페이지가 안보이거나 330 오류가 날 때는 이렇게 해결! [2] | 세라오빠 | 2011.04.13 |
(1.4.5 버전 이상) XE가 설치된 사이트 찾기 [1] | SMaker | 2011.04.17 |
댓글 쪽지 알림시 원본글 URL 설정 [1] | unnumiya | 2011.04.15 |
1.4.5.2로 업데이트 후 짧은 주소가 제대로 되지 않으실때... [8] | 라르게덴 | 2011.04.12 |
다솜플레이어창은 뜨는데 연결중에서 더이상 안넘어가요 | 탱7 | 2011.04.15 |
1.4.4.2부터 게시판 신규게시물 작성이 안되던 문제 [2] | 운상유희 | 2011.03.25 |
업데이트 어떻게 해야 오류 없이 되나요? [1] | 김농주 | 2011.04.12 |
텍스타일 카테고리 글목록수 수정 | 신군임니돠 | 2011.04.12 |
제로보드 XE - 오토셋에 설치하기 [11] | 차오이 | 2007.08.11 |
레이아웃에 소스추가해서 트래픽보기! [2] | 막시민 | 2011.03.07 |
회원가입폼 내멋대로 내맘대로 하기. [9] | 지인짜 | 2010.08.04 |
[모바일] 모바일웹에서 Pc버전갔다가 다시 모바일버전으로 갈라면 [1] | 푸름빠 | 2011.04.07 |
XE로 API 처리 완전 정복하기(2) [2] | 라르게덴 | 2009.11.03 |
P 개행처리를 BR처럼 | Garon | 2011.04.04 |
데이터이전 회원관련해서 알아야 할 사항 [2] | 푸름빠 | 2011.04.03 |
[PHP 기초] 변수, 상수 [2] | 난다날아 | 2011.03.24 |
관리자페이지 레이아웃에 게시판을 달아보자 [3] | 푸름빠 | 2011.03.29 |
"현재 xe코어1.4.4.4버전에서는 익스플로어에서 페이지수정 등의 작업을 할때 에러가 자주 발생하곤 합니다." | 유샤인 | 2011.03.29 |
디버그모드 변경하는 간단한 파이썬 스크립트 [4] | mmx900 | 2008.04.23 |
모두 새로 코딩된 선우님의 새로운 레이아웃.... | 유샤인 | 2011.03.28 |
api class를 이용하여도 되고 model class를 이용해도 됩니다.
즉 model class의 member method를 action으로 취급해서 할 수도 있죠