プログラミング工房
TOP
Flex基本
開発環境 JavaScript連携 PHP連携1 PHP連携2(AMFPHP) ウィンドウ ボタンスキン 矩形スキン ローカルファイル(テキスト) F5等の対策 ローカルファイル(イメージ) ダウンロード、アップロード 1枚の画像のカラーを変更 時間のかかる計算処理 外部SWFの読込み
Flexで3D
Flexだけで3D Papervision3Dを使ってみる 3Dオブジェクト カメラ、前後判定の工夫しました 自由な形状を作成
Flexでクラス
Class1(白黒ゲームの盤) Class2(白黒ゲームのプレイヤー) Class3(プレイヤーを外部SWF)
PHP
共通関数1
Flexの作品
お問合せの説明 サンプルのソース表示の説明 分子構造の表示(PDBファイル) マンデルブロ集合の画像作成 swf参加型白黒ゲーム(Reversi) ストップウォッチ WEB素材
AIR
AIRを使ってみる ソースファイルのHTML変換を作る
etc.
マンデルブロ集合のギャラリー ジュリア集合のギャラリー wonderflを使ってみました お問合せ

Flex4基本-PHP連携2(AMFPHP)

■2011.02.17:作成
サンプル サンプルのソース

AMFPHPとは

AMFPHPとは簡単に言うと、変換しないでFlexのデータ(配列など)をそのままPHPで利用できるようにしたPHPのライブラリです。
詳しく知りたい人は「Action Message Format(AMF)」等で検索してください。

AMFPHPはhttp://amfphp.org/から ダウンロード出来ます。
ダウンロードしたZIPファイルを解凍し適当なフォルダ(ディレクトリ)に置いてください。
私の環境では"C:\xampp\htdocs\flex4\[プロジェクト名]\php_lib\amfphp"に置きます。

Flex側のプログラム

FlexからPHPの関数を呼び出す側は以下のような事を行います。
 ・PHPから帰ってきた時に呼ばれる関数の定義
   flexToPHP2Get:正常終了の時、呼ばれる関数
   onFault:エラー終了の時、呼ばれる関数
 ・PHP側のプログラムを指定(「Flex4基本-PHP連携1-PHPのパスに関して」を参照)
   実際はGateway.php→Service.phpの関数になります。
 ・PHPのflexToPHP2関数の実行
   サンプルのPHPに渡すパラメータは
     strTitle:タイトル(文字列)/arrInDat:DataGridのデータ(連想配列の配列)
   となります。
//PHP連携の開始
private function onFlexPHP(event:MouseEvent):void {
    //PHPに送信するデータセット
    var strTitle:String=taTitle1.text;
    var arrInDat:Array = dgDat1.toArray();
    
    nuSt = getTimer();  //開始時刻セット

    //PHPから戻ったときの関数
    var responder:Responder = new Responder(flexToPHP2Get, onFault);
    var connection:NetConnection = new NetConnection();
    //実行するPHP
    connection.connect(strPhpUrl+"Gateway.php");
    connection.objectEncoding = ObjectEncoding.AMF3;
    // PHPのServiceクラスのflexToPHP2メソッドを呼び出す
    connection.call("Service.flexToPHP2", responder,strTitle,arrInDat);
}

PHPから戻ったときのデータは1個しかないので配列で受け取ります。
  サンプルのPHPからのデータは
   arrDat[0]:PHPの処理でエラーが発生したときのエラー内容(文字列)
   arrDat[1]:タイトル(文字列)
   arrDat[2]:DataGridのデータ(連想配列の配列)
   arrDat[3]:PHPでの処理時間(実数)
  です。
// データ取得成功
private function flexToPHP2Get(arrDat:Array):void {
    if (arrDat[0] != "") {
        Alert.show("エラー:" + arrDat[0], "FlexPHP2");
        return;
    }
    var nuTime:Number = getTimer()-nuSt;    //終了時刻セット
    var i:int;
    
    taTitle2.text = arrDat[1];
    dgDat2= new ArrayCollection();
    for (i = 0; i < arrDat[2].length; i++) {
            dgDat2.addItem(arrDat[2][i]);
    }
    taTime.text = "Flex->PHP->Flexの処理時間=" + nuTime + "ミリ秒\n" +
                  "PHPの計算時間=" + arrDat[3] + "ミリ秒";
}

エラーの時の関数
// データ取得失敗
private function onFault(e:*):void{
    Alert.show("通信失敗","FlexPHP2");
}

PHP側のプログラム

PHP側の処理はGateway.php→Service.phpの関数が実行されます。

Gateway.phpでは
 ・amfphp/core/amf/app/Gateway.phpをインクルードします。
   (AMFPHPを置いたディレクトリを指定してください)
 ・Service.phpのあるパスを指定する。(今回は同じディレクトリ)
<?php
// Gateway.php
include '../../php_lib/amfphp/core/amf/app/Gateway.php';
function main(){
    $gateway = new Gateway();
    $gateway->disableDebug();
    $gateway->setClassPath(".");
    $gateway->enableGzipCompression(25*1024);
    $gateway->service();
}
main();
?>

Service.phpに関して
 ・クラスにします。
 ・クラス内にflexToPHP2関数を作ります。
   引数はPHPの変数としてそのまま利用できます。
 ・実数を文字型に変換(下の「FlexとPHPでの実数のあつかい」を参照)
 ・PHPからの戻り値は1個なので配列にセットします。
<?php
// Service.php
class Service{
    public function flexToPHP2($title,$arrInDat){
        mb_internal_encoding("UTF-8");
        //PHPでエラーが発生したときエラーメッセージをセット
        $err = "";
        // 現在の開始時間を格納
        $startTime = microtime(true);
        //返信データをセット
        $reTitle = $title."<加減剰余>";
        $arrReDat=array();
        foreach ($arrInDat as $dat) {
            //計算結果はは文字列としてセット
            //(Flex<->PHP間で12.1 -> 12.100000001となることがあるため)
            array_push($arrReDat,
                array("name" => ($dat["name"]."の結果"), 
                      "add" => "".($dat["x"]+$dat["y"]),
                      "sub" => "".($dat["x"]-$dat["y"]),
                      "mult" => "".($dat["x"]*$dat["y"]),
                      "div" => "".($dat["x"]/$dat["y"]),
                )
            );
        }
        // 計測完了時の時間を格納
        $endTime = microtime(true);
        // [終了した時間]と[開始した時間]の差が実際に掛かった時間。
        $tim= ($endTime - $startTime)*1000 ;
        //Flexへ返信
        $arrData = array($err, $reTitle, $arrReDat,$tim);
        return $arrData;
    }
}
?>

PHPのテストプログラム

Service.phpの試験に関して
以下のようなテストプログラムを作ればFlexと独立でPHPのテストが行えます。
 ・Service.phpをインクルード
 ・テストしたい関数を実行
<?php
//ServiceのTEST用
include "Service.php";
//入力データ作成
$title = "TEST";
$arrInDat=array(
    array("name" => "abc", "x" => 724.1, "y" => 669.5),
    array("name" => "xyz", "x" => 1.3, "y" => 2.2)
);
//関数の実行
$obj = new Service();
$arrDat = $obj->flexToPHP2($title,$arrInDat);
//入力・出力データの出力
print "title=".$title."<br/>";
print "arrDat=<br/>";
foreach ($arrInDat as $dat) {
    print " name=".$dat["name"]." x=".$dat["x"]." y=".$dat["y"]."<br/>";
}
print "<br/>"; 
print "arrDat[0]=".$arrDat[0]."<br/>"; 
print "arrDat[1]=".$arrDat[1]."<br/>"; 
$arrReDat = $arrDat[2];
print "arrDat[2]=<br/>";
foreach ($arrReDat as $dat) {
    print " name=".$dat["name"]." add=".$dat["add"]." sub=".$dat["sub"].
        " mult=".$dat["mult"]." div=".$dat["div"]."<br/>";
}
print "arrDat[3]=".$arrDat[3]."<br/>";
?>

FlexとPHPでの実数のあつかい

AMFPHPを利用すれば色々な変数を型変換せずにそのまま利用できます。
但し実数に関してPHPの"12.1"が、Flexでは"12.100000001"の様な事が起こります。

これは10進(0.1)=2進(0.00011001100110011・・・・)と循環小数になります。
FlexとPHPの実数の扱いが多少異なる為だと思います。(?)

今回のプログラムは実数を文字列に変換してFlex・PHP通信を行っています。

プログラミング工房