PHP는 HTTPService말고 방법이 없을까 하고 찾아보니, Zend에서 AMF를 이용하여 개발한게 있군요. Adobe의 공식 지원으로 만들어진거라 빠르리라고 생각합니다^^ (적어도 HTTPService보단 빠르겠죠!)
암튼, BlazeDS를 하셨다면 그리 어렵지 않군요.
이번에도 간단하게 소녀시대예제를 통해...접근해봅시다-_-;
간단히 데이터를 불러오고, 저장도 해보는 그런 애플리케이션을 만들어봅시다.
우선 Eclipse에서 php가 가능하도록 해야하는데요. 뭐 그냥 editplus에서 해도 상관없습니다. Zend홈페이지에 가면 자기네들 IDE깔라고 합니다-_-; Zend Studio라는 게 있네요. 뭐 php단은 netbeans를 이용해서 개발하셔도 되고, 이클립스에 있는 PDT를 추가하셔서 해도 상관없어요~ ^^ 전 NetBeans를 선호합니다. 좋아요!
DB입니다.
[code]DROP TABLE IF EXISTS `sosi`.`sosi`;
CREATE TABLE `sosi`.`sosi` (
`idx` int(10) unsigned NOT NULL AUTO_INCREMENT,
`sosiname` varchar(45) NOT NULL,
`height` int(10) unsigned NOT NULL,
`blood` varchar(45) NOT NULL,
PRIMARY KEY (`idx`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
INSERT INTO `sosi` (`idx`,`sosiname`,`height`,`blood`) VALUES
(1,'윤아',166,'B'),
(2,'수영',170,'O'),
(3,'효연',160,'AB'),
(4,'유리',167,'AB'),
(5,'태연',162,'O'),
(6,'제시카',163,'B'),
(7,'티파니',162,'O'),
(8,'써니',158,'B'),
(9,'서현',168,'A');[/code]
우선 Flex Project를 만듭니다.
여기서 Application server type을 php로 하세요~ php로 하게 되면 설정된 폴더로 swf를 바로 위치시킬 수 있어요!
Project name은 ZendAmfTest -> Web root는 아파치가 돌아가는 폴더를 지정하면 됩니다.
저는 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs여기군요.
Root URL은 http://localhost/ Finish때려주면 ZendAmfTest-debug폴더에 swf가 생기죠.
요 아래 주소에서 ZendAMF를 받을 수 있습니다.
http://framework.zend.com/download/amf받은 다음에 압축을 풀면 library폴더 안에 Zend라는 폴더가 있는데 통채로 복사해서 src폴더 아래에 놓습니다.
그리고 php파일을 하나 만드세요. ValueObject입니다. Java에서 bean같은..-_-;
SosiVo.php[code]<?php
class SosiVo {
public $idx;
public $sosiname;
public $height;
public $blood;
}
?>[/code]
이제 서비스를 하나 만들어봅시다. SosiService입니다.
SosiService.php[code]<?php
require_once 'SosiVo.php';
//conection info
define("DATABASE_SERVER", "localhost");
define("DATABASE_USERNAME", "root");
define("DATABASE_PASSWORD", "mudchobo");
define("DATABASE_NAME", "sosi");
class SosiService {
public function getData() {
$mysql = mysql_connect(DATABASE_SERVER, DATABASE_USERNAME,
DATABASE_PASSWORD);
mysql_select_db(DATABASE_NAME);
$query = "SELECT idx, sosiname, height, blood FROM sosi";
$result = mysql_query($query);
$ret = array();
while ($row = mysql_fetch_object($result)) {
$tmp = new SosiVo();
$tmp->idx = $row->idx;
$tmp->sosiname = $row->sosiname;
$tmp->height = $row->height;
$tmp->blood = $row->blood;
$ret[] = $tmp;
}
mysql_free_result($result);
return $ret;
}
}
?>[/code]
php의 array는 ActionScript3의 array와 호환됩니다.
서비스를 만들었으니 EndPoint페이지를 만들어줘야합니다.
amf.php[code]<?php
require_once 'Zend/Amf/Server.php';
require_once 'SosiService.php';
$server = new Zend_Amf_Server();
$server->setClass("SosiService");
$server->setClassMap("SosiVo", "SosiVo");
echo($server -> handle());
?>[/code]
이제 이것을 연결시켜줄 service-config.xml파일을 만들어야합니다.
[code]<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service id="amfphp-flashremoting-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">
<default-channels>
<channel ref="my-zend"/>
</default-channels>
<destination id="zend">
<properties>
<source>*</source>
</properties>
</destination>
</service>
</services>
<channels>
<channel-definition id="my-zend"
class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://localhost/ZendAmfTest-debug/amf.php"
class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>
</services-config>[/code]
우선 default로 my-zend라는 채널을 잡았는데, my-zend는 endpoint uri가 ~~/amf.php입니다. 우리가 좀전에 작성했던 endpoint죠. 새로운 서비스가 추가되어 새로운 endpoint를 작성하게 될 때 endpoint파일을 amf1.php라고 했을 때 이곳에 추가해서 channel에 기입할 수도 있고, <mx:RemoteObject>에서 endpoint를 해당 uri로 바꿔주는 방법 2가지가 있습니다.
그럼 이제 Flex쪽으로 넘어가봅시다.
ZendAmfTest.mxml[code]<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
creationComplete="creationCompleteHandler()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
private function creationCompleteHandler():void
{
roSosi.getData();
}
private function faultHandler(event:FaultEvent):void
{
Alert.show(event.message.toString());
}
private function resultGetDataHandler(event:ResultEvent):void
{
dgSosi.dataProvider = event.result as Array;
}
]]>
</mx:Script>
<mx:RemoteObject id="roSosi" fault="faultHandler(event)" destination="zend" source="SosiService">
<mx:method name="getData" result="resultGetDataHandler(event)" />
</mx:RemoteObject>
<mx:DataGrid id="dgSosi" width="100%" height="100%">
<mx:columns>
<mx:DataGridColumn headerText="아이디" dataField="idx"/>
<mx:DataGridColumn headerText="소녀시대이름" dataField="sosiname"/>
<mx:DataGridColumn headerText="신장" dataField="height" />
<mx:DataGridColumn headerText="혈액형" dataField="blood" />
</mx:columns>
</mx:DataGrid>
</mx:Application>[/code]
만약 다른 서비스를 추가하게 된다면, <mx:RemoteObject>에서 endpoint를 다른 url로 잡아주면 됩니다.
[code]<mx:RemoteObject id="roAnother" fault="faultHandler(event)"
destination="zend" source="AnothorService"
endpoint="http://localhost/ZendAmfTest-debug/another_amf.php">[/code]
아님 service-config.xml에서 channel을 다르게 해서 destination을 다르게 설정해도 되구요.
ps1. 다른 예제에서는 2개의 service를 이용한 예제가 없더라구요. 그래서 사실 저렇게 하는 게 맞는지 잘 모르겠습니다. 다른 방법이 있을 수도 있구요^^ 암튼, 제가 삽질한 바로는 서비스당 1개의 php파일을 만들어야 하더라구요.
ps2. PHP를 시작한지 얼마 안되었는데, DB연동 시 한글이 깨지더라구요. 인코딩을 my.ini과 php.ini에 utf-8로 맞췄는데, ???로 인식해서 나오는 경우가 있더라구요. php파일에서 db정보를 출력하니 이상하게 그냥 로컬에서 쳤을 때에는 utf-8로 나오는데, php파일이 출력한 db정보는 latin으로 나올 때가 있더라구요. 이 경우 my.ini파일에 이 부분을 추가해주면 됩니다.
[mysqld] 아래에
character-set-client-handshake = FALSE
client 인코딩으로 강제 셋팅하는거라고 하더라구요. 저는 처음에 ??? 뜨길래 이걸로 해결봤습니다-_-;
아 또 다른 방법으로 쿼리날리기 전에 set names 'utf8'이라고 먼저 날려줘도 됩니다.
[code]mysql_query("SET NAMES 'utf8'");[/code]
ps3. 이런...생각해보니 client에서 VO를 안만들어줬군요-_-;
참고자료
http://corlan.org/2008/11/13/flex-and-php-remoting-with-zend-amf/덧. 채널 못찾는 에러는 아래 주너니님의 댓글을 참조하세요~ 컴파일옵션을 추가해야합니다^^
주너니님 감사합니다 ^^