웹마스터 팁
XE로 API 처리 완전 정복하기(2)
2009.11.03 14:23
XE로 API 처리 두번째
참고
첫번째 설명에 사용된 내용을 (1) 이라는 명칭으로 사용합니다.
목차
- board.api.php 흐름 이해
- FileHandler::getRemoteResource() 구조, header 선언
- blogapi 애드온으로 metaWeblog 글 입력하기
- api 처리용 심플 모듈 만들어보기
1. board.api.php 흐름 이해
1 2 3 4 5 6 7 8 9 10 11 | <?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와 같은 변수를 넘기지 않아 오류가 발생되니 주의가 필요합니다.
1 | < 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를 접근하여 아래의 소스가 동작하게 되고
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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는 각종 파일 입출력 복사 등 데이터 처리에 대한 전반적인 기능들이 포함되어있기 때문에 활용하시면 큰 도움이 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <?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 안에서 선언되거나 활용되어 집니다. 별도의 값이 필요하다면
1 2 3 4 | 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가 꼭 붙어야 하며 끝에 / 는 넣지 마십시오.
글 조회
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?php $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 ; ?> |
확인
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | < 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 >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)에도 설명했지만 알아서 파싱해서 활용하셔야겠지요.
글 입력
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?php $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 ; ?> |
1 2 3 4 5 | <? xml version = "1.0" encoding = "utf-8" ?> < methodResponse >< params >< param > < value >< string >71</ string ></ value > </ param ></ params > </ methodResponse > |
이런 내용이 나오면 성공입니다.
※ 카테고리의 경우 번호를 입력해야하는지 등록되어있는 실제 이름을 입력해야하는지는 확인 안해봐서 잘 모르겠네요.
첨부파일 등록
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?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을 아래와 같이 만듭니다.
1 2 3 4 5 6 7 8 | <? xml version = "1.0" encoding = "utf-8" ?> < module > < grants /> < permissions /> < actions > < action name = "dispContentView" type = "view" index = "true" /> </ actions > </ module > |
모듈/모듈.class.php를 아래와 같이 만듭니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php class 모듈 extends ModuleObject { function moduleInstall() { } function checkUpdate() { return false; } function moduleUpdate() { return new Object(0, "success_updated" ); } function recompileCache() { } } ?> |
모듈/모듈.view.php를 아래와 같이 만듭니다.
1 2 3 4 5 6 7 8 | <?php class 모듈View extends 모듈 { function init() { } function dispContentView() { } } ?> |
- view에서 Context::set()에 처리 결과를 넣고 api로 활용할지 사용할 수 있습니다.
- 아무것도 할일 없다고 해서 함수를 없애면 api.php가 동작하지 않습니다. 껍데기라도 만드셔야 합니다.
1 2 3 4 5 6 7 8 9 10 | <?php class 모듈Model extends 모듈 { function init() { } function _dispContentView( $args ) { $args ->model = "모듈Model" ; return $args ; } } ?> |
모듈/모듈.controller.php를 아래와 같이 만듭니다.
1 2 3 4 5 6 7 8 9 10 | <?php class 모듈Controller extends 모듈 { function init() { } function _dispContentView( $args ) { $args ->controller = "모듈Controller" ; return $args ; } } ?> |
모듈/모듈.api.php를 아래와 같이 만듭니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?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 선언에 따라 포멧을 만들어 내보냅니다.
테스트
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?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" ); $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 ; ?> |
1 2 3 4 5 6 | < 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
제목 | 글쓴이 | 날짜 |
---|---|---|
모듈 선택기에서 선택이 안되는 문제해결. | 모글리만세 | 2011.04.22 |
QRCode 이미지를 줄여서 깔끔하게사용하는 법~ [2] | 포토올/wow | 2011.04.18 |
갑자기 관리자 페이지가 안보이거나 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 |
api class를 이용하여도 되고 model class를 이용해도 됩니다.
즉 model class의 member method를 action으로 취급해서 할 수도 있죠