高見龍

iOS app/Ruby/Rails Developer & Instructor, 喜愛非主流的新玩具 :)

AMFPHP - 搭起 Flash 與 PHP 的美麗橋樑

image

Flash在跟Server在交換資料,比較常見的是一般的文字訊息或是XML,我自己在趕時間的時候,會偷懶的隨便echo一個字出來知會Flash說server程式已經做完了或是程式執行之後的結果,不趕時間且資料量較多的時候,則會乖乖的用XML。不過,最近開始我比較常用的是AMF跟JSON這兩個方法,其實都還滿方便的,各有其優缺點。

AMF(Action Message Format),由Adobe公司推出的規格,主要是用來給flash以RPC的方式來交換資料用的,在flash player 6的版本就已經開始支援(AMF0),直到flash player 9才又推出新規格(AMF3)。其它細節可參考:http://en.wikipedia.org/wiki/Action_Message_Format

接下來就來個簡單的實作吧 :)

1. 下載AMF gateway

找個自己順手的語言

  • AMFPHP:這是PHP的
  • PyAMF:這是Python的(還不熟,努力學習中)
  • AMF.NET:這是.NET的

光看名字大概就能猜到它的後端是用什麼做的。其它還有for Java或其它的,有興趣的可以繼續google翻翻看。

2. 安裝AMF gateway(以AMFPHP為例)

安裝方法很容易的,只要把下載下來的壓縮檔解開,放在Web server底下一個自己找得到的路徑就行了。我是放在http://127.0.0.1/test/amfphp/底下。

AMFPHP有提供一個很棒的Service Browser,網址是http://127.0.0.1/test/amfphp/browser,這是個用Flex做的介面,可以清楚列出目前在AMF gateway上的服務。

3. 在AMF gateway上新增一個服務

我做了一個簡單的php類別檔,存檔為callme.php,並放在AMF gateway的services資料夾裡面(文末有原始檔連結)。PHP不像Java或AS3一樣硬性規定類別名稱一定要跟檔名一樣..至少php5還沒有,但建立這習慣也不錯。

1
2
3
4
5
6
7
8
<?php
  class callme
  {
      function callmeplease($text)
      {
          return $text;
      }
  }

上面,我做了一個callme的類別,然後裡面放了一個callmeplease的方法,這個方法會接收一個參數,執行完成之後,會把傳入的參數return回來。這裡只是簡單直接return而已,更複雜的資料庫存取程式也可以寫在這裡…

接下來看一下Service Browser,會發現寫寫的那個新的服務在的左手邊的列表裡:

image

在右邊的Text輸入文字,按一下右邊的「Call」,應該就可以直接看到結果。(中文支持問題請見文末補充)

4. 新增一個Fla(這裡以AS3.0為例)

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
import flash.net.*;

// 新增一個NetConnection物件
var test:NetConnection = new NetConnection();

// 連上AMF gateway
// 這裡每家AMF gateway的實作方法應該都有差別,細節請記得看該實作說明
test.connect('http://127.0.0.1/test/amfphp/gateway.php');

// 準備一個Responder物件來接收事件,用法及參數請參考F1說明
var returnResult:Responder = new Responder(ok, ng);

function ok(res:Object):void {
  trace(res);
}

function ng(res:Object):void {
  trace(res);
}

//以上,我做了ok跟ng兩個簡單小function,分別是trace出它們接收到的物件

test.call('callme.callmeplease', returnResult, 'hi, flash');
// 這裡是最重要的動作,就是直接用call這個方法
// "呼叫"在gateway上面的callme這個服務裡的callmeplease這個方法
// 第二個參數是接收反應的responder,第三個參數是給callmeplease的參數

以上,callme.callmeplease會把”hi, flash”傳給AMF gateway,然後gateway回傳”hi, flash”回來給flash。順利的話,Ctrl + Enter執行,就會在output視窗看到輸出的東西了。

就這樣,你的Flash已經可以跟各家有支援AMF的gateway”對談”了。

上面提到的原始檔在這裡可以拿得到(其實沒幾行字,就一個.php跟.fla)

還是看不懂嗎? 沒關係,這裡有個很棒的影音教學,看完跟著作一遍就知道大概是怎麼運作的了 http://www.gotoandlearn.com/player.php?id=78

希望對大家有幫助 :)

補充1:

AMF不久之後已經可以在Zend Framework裡找到native module了,ZF真的是包山包海了 :) ((而且ZF-AMF就是由AMFPHP裡的主導人Wade Arnold來親自操刀)。

補充2:

AMFPHP預設的編碼是不支援中文的(會出現亂碼),不過只要修改一下gateway的程式碼即可。

使用文字編輯器,開啟AMFPHP資料夾的gateway.php,應該可以找到一段跟字碼有關的:

$gateway->setCharsetHandler("utf8_decode", "ISO-8859-1", "ISO-8859-1");

把它修改成:

$gateway->setCharsetHandler("utf8_decode", "UTF-8", "UTF-8");

或是如果你的PHP模組裡有iconv的話也可以這樣改:

$gateway->setCharsetHandler("iconv","UTF-8","UTF-8");

記得,不要改flash裡的useCodePage = true,雖然可能也ok,但這是走回頭路…能使用Unicode就盡量使用它吧 :)

dojo toolkit入門(一)

image

雖然我個人還是比較喜歡jQuery的簡潔方便,而且一些常用的function也都jQuery化了,不過畢竟DojoZend Framework 1.6版後就被officially的收進去了,為了ZF寫起來的完整性,還是花點時間來研究一下。

廢話不多說,先來試玩一下!

步驟一:下載它

dojo toolkit的網站即可下載(不過其實也可以不用下載..請見步驟二)

步驟二:安裝它

基本上,下載壓縮檔回來後,解壓縮後放在你的網頁的目錄(放哪裡都可,只要你能找得到就好)。假設我放在js/dojo底下,接下來只要一行:

<script type="text/javascript" src="js/dojo/dojo/dojo.js"></script>

這樣就算完成安裝了..

除了這種方式外,也有不用下載整包回來的方法,就是使用別人家(CDN or Google)準備好的服務:

1. AOL的CDN(Content Delivery Network)

<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.1.1/dojo/dojo.xd.js"></script>

2. Google Ajax Libraries API:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.1.1/dojo/dojo.xd.js"></script>

註:Google上還有host別的Ajax library(如jQuery、MooTools..等),詳情請洽Google Ajax Libraries API

使用線上版跟本機版各有優缺點,線上版的好處就是省頻寬,畢竟dojo整包檔案解開壓縮也不小,有十幾MB,若能使用像Google這種又快又穩定的主機頻 寬來host,多少也是可以省一些的;當然缺點就是畢竟是別人家免費提供的服務,萬一有什麼”萬一”的話,可能會導致全站的功能都出問題。而本機版的優缺 點就剛好跟線上版的相反(個人比較偏好本機版安裝法)。

步驟三:使用它

在步驟二的地方,當你指定<script>src的時候,其實就已經使用了。先來試一下DOM selector跟onLoad事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Dojo Test</title>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.1.1/dojo/dojo.xd.js"></script>
<script type="text/javascript">
  dojo.addOnLoad(function(){
    dojo.byId("test1").innerHTML = "Hello, Dojo";
    dojo.connect(dojo.byId("btn1"), "onclick", function(evt){
      alert("Hello again, Dojo!");
    })
 });
</script>
</head>
<body>
<div id="test1"></div>
<input type="button" value="clickme!" id="btn1" />
</body>
</html>

線上測試

簡單的說明上面用到的幾個功能:

1. dojo.addOnLoad

就是在頁面讀取完成之後會做的事,有點像一般的onLoad功能,不過順序在它之後

2. dojo.byId(“test1″)

這將會回傳在頁面裡面叫id叫做test1的元素(在上面這裡是一個div),功能有點像原來的document.getElementById()。再透過設定這個回傳回來的物件的innerHTML的值,就可以直接讓這個Div區塊裡面的值有變化。

3. dojo.connect()

這個比較有趣,這個function可以傳入四個參數。第一個是參數是物件,第二個參數是事件(字串),第三個參數也是物件(可省略),第四個參數是要綁的事件(字串),可以另外在別的地方定義好function再掛上來,也可以像上例一樣直接給它一個anonymous function 簡單的說,dojo.connect()可以翻譯成「把某個事件(或function),綁到某個物件的某個事件(或function)上」,直接來看上面的例子:

1
2
3
dojo.connect(dojo.byId("btn1"), "onclick", function(evt){
  alert("Hello again, Dojo!");
})

以上例來翻譯成白話文就是說「我把一個anonymous function,綁到id為btn1的那個按鈕的onclick事件上」,所以,當觸發這個按鈕的onclick事件(也就是點擊它),就會跟著觸動這個function,丟出”Hello again, Dojo!”的字樣出來。

更多的細節可再參考Dojo的線上手冊。

目前國內用dojo的人看起似乎並不多,日前去書局弄了一本Dojo-The Definitive Guide,仍在研究中,看來這個Dojo能做的事情還挺多,有心得再來繼續貼。

Omit the PHP closing tag “?>”

自從開始改用ZF後,開始慢慢的調整自己的code style,過程也許會痛苦,但相信結果應該會是甜美的。在ZF的Coding Standard裡有一段是這麼寫的:

For files that contain only PHP code, the closing tag (“?>”) is never permitted. It is not required by PHP, and omitting it prevents the accidental injection of trailing whitespace into the response.

看不太懂哪來的injection,後來再翻了一下PHP的官方資料才發現也有提到這段:

The closing tag of a PHP block at the end of a file is optional, and in some cases omitting it is helpful when using include() or require(), so unwanted whitespace will not occur at the end of files, and you will still be able to add headers to the response later. It is also handy if you use output buffering, and would not like to see added unwanted whitespace at the end of the parts generated by the included files.

後來自己動手做了一下實驗:

檔名 inc.php

1
2
3
<?php
// do something
?>

檔名:test.php

1
2
3
4
<?php
require_once('inc.php');
session_start();
?>

執行test.php,看起來是沒什麼大問題;不過如果在inc.php的”?>”後面再按幾下enter,多加幾行空白行,test.php就會丟出警告訊息”Cannot send session cookie – headers already sent by..”,如果把inc.php的”?>”拿掉就ok了。

原來,在”?>”之後多按的幾個enter(newline)也會被當成資料丟給瀏覽器,所以如果include了這樣的檔案進來,會讓header()session_start()之類的指令丟出”headers already sent by..”的警告訊息,而如果省去結尾的”?>”則可以避免這個問題。

果然魔鬼都是還是躲在細節裡,PHP的手冊還是要多看啊!

順帶一提,ZF有PDF版的離線手冊了,一千多頁,雖然不見得有比線上方便,但沒網路的時候倒還不錯用(我是把它放到PDA裡,上廁所可以看)

Zend Framework之Zend_Tool

看到DjangoRails之類的Web Framework都有可以快速的產生scaffold的工具,甚至連同樣都是PHP framework的CakePHP也有..還好我之前都是在Zend Studio裡直接new一個Zend Framework Project,它也會自動產生基本的架構出來。隨著Zend Framework 1.6版的上市,它也提供了類似的方便工具(不過從目錄名字看起來還是在實驗階段而已..)

我的作業環境是WinXP,如果要在別的系統可參考最底下的參考資料,有提到怎麼修改路徑。

簡單的使用方法如下:

Step 1.

ZF官網下載Zend Framework 1.6,解壓縮之後裡面有個laboratory資料夾,裡面有個ZendL,把它放到你的include_path底下。

Step 2.

在laboratory/Zend_Tool/bin裡有個zf.bat跟zf.php,改一下zf.bat裡的php.exe的路徑(如果放在跟php.exe同目錄就不用改了)

Step 3.

以上設定完成之後,到cmd模式下,輸入zf show version,應該會出現「Zend Framework Version: 1.6.0」字樣

Step 4.

隨便找一個資料夾來試試,輸入zf create project,等一會,它就會幫你把資料夾跟檔案產生好了(如下圖)

image

完成! 這樣就完成了基本的ZF MVC的骨架出來了,也做了簡單的bootstrap跟幾個預設的controller跟view。不過我發現這個Zend_Tool會把ZF的 library整個也複製一份到library底下,雖然是方便發布,不過我個人是習慣不把它放在web資料夾下..

結論:不管是Zend Studio或是Zend_Tool都可以快速的產生架構出來,我還是習慣用自己的架構..

參考資料:Zend Developer Zone

Zend Framework 1.6 Release

之前用了一陣子的RC版,今天終於正式Release了,這個1.6版的ZF比1.5版多了不少有趣的東西啊(不過選在跟新聞炒很大的google chrome同一天出來,鋒頭多少被蓋去了一點點)

  • Dojo Integration
  • SOAP
  • Preview of Tooling Project in Laboratory (see /laboratory folder)
  • Unit Testing Harness for Controllers
  • Lucene 2.3 Index File Format Support
  • Zend_Session save handler for Database Tables
  • Paginator Component
  • Text/Figlet Support
  • ReCaptcha Service
  • Captcha Form Element
  • Zend_Config_Xml Attribute Support
  • Zend_File_Transfer Component
  • File Upload Form Element
  • Zend_Wildfire Component with FireBug Log Writer
  • Media View Helpers (Flash, Quicktime, Object, and Page)
  • Support in Zend_Translate for INI File Format

對我工作上比較大的影響是跟Dojo的整合(我還是比較喜歡jQuery),這裡有篇文章有寫到1.6版新增的一些功能介紹。

另外,分頁、表單認證碼及檔案上傳功能…這些在做網站時常用的功能,之前都是自己拼裝出來用的,結果在1.6也都加進來了 :) 。我試著直接把1.5版昇級為1.6版,目前手邊的案子看起來都還滿正常的。

下載連結:http://framework.zend.com/download/current/