發新話題
打印

Ajax程式設計--使用xajax(server side ajax)

Ajax程式設計--使用xajax(server side ajax)

原文請參考:
http://gridv6.csie.chu.edu.tw/blog/archives/21

--
這一篇文章主要是教導各位怎樣在php的環境上開發Ajax程式
如果要撰寫ajax,HTML及JavaScript的基礎是相當必要的。

    * Server Side及Client Side

要探討Ajax之前,我們必須先定義上面這兩個名詞。早期的CGI程式設計(這是一個很老掉牙的名詞),就是一種最標準的伺服器端(Server Side)程式設計,這個代名詞對很多老一派的Web程式設計師都應該不陌生。CGI是一種規格,而在php都還沒開始的年代,大家都是用Perl來實做。然而php的出現,他更簡易的語法及簡單的物件導向設計,使得很多人前仆後繼。而MySQL這開放原始碼且簡單好用的資料庫系統,加上php的支援,以及Apache的穩定,讓他們成為最好的搭檔。

用戶端程式(Client Side)設計泛指使用HTML,CSS,JavaScript(以下我們簡稱JS)等瀏覽器才能解析的語言來撰寫程式的方式。用戶端程式設計的好處是,所有的結果會即時反應在瀏覽器上,因為資料不需要重新傳送回去伺服器,也就不會有任何的畫面更新。很常見到的是很多人會去找JS特校,所以JS也快變成網頁特效的代名詞。而現在撰寫JS除了要注意瀏覽器的支援問題以外,JS的除錯也是得由瀏覽器支援,例如像IE就不是很好除錯JS程式碼,而Firefox 還可以支援中斷點。

下面有三個時鐘範例:

時鐘1

時鐘2

時鐘3

看起來是相同的結果,其實完全不一樣。第一個是用JS寫的,第二個是用Ajax寫的,第三個是PHP,稍後我將實際解釋程式碼。

    * 什麼是Ajax

Ajax就是Asynchronous JavaScript And XML,Ajax發音做A-jacks。這樣的程式撰寫方式不限定任何一個語言平台,想要的話C也可以寫Ajax。要討論同步或非同步,我們要先看第三個php時鐘的程式碼。

<!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>PHP 時鐘</title>
</head>


<body onload="setInterval('form1.submit()',1000)">
<form id="form1" name="form1" action="index.php" method="post">
  現在的時間 :
  <input name="time" type="text" id="textbox" size="28" value="<?php print(date('H:i:s')); ?>" />
</form>
</body>
</html>

你可以注意到,在這樣的情況下,Client和Server的通訊大概會是像:
Client -> HTTP POST -> Server PHP
Client -> 等待Server PHP回應
Server PHP -> 回應 -> Client
這樣的流程。我們之所以說是同步,是因為Client一定要等待整個php程式執行完後,資料傳送回來,才會更新畫面。

為了達到每一秒更新時間的效果,就要每一秒呼叫form1.submit()。如此便會造成畫面的閃動。根據瀏覽器再次將整個回應的HTML讀入到記憶體,如果你回應的HTML很大,或是你有多個物件都在做每秒更新的動作,也不見得會是剛好一秒了。但是可以見到,這樣是最單純的寫法,也是被大家廣為接受的Web程式設計模式。

那非同步是怎樣呢?在Ajax的設計方法之下,他們的通訊會是像這樣:
Client -> 將要求的XML傳送到Server PHP
Client -> 不會發生任何畫面改變
Server -> 將要變更的項目封裝成XML -> Client
Client -> 解析XML之後並且更新畫面
不要太介意非同步這個名詞,他只是為了要區別以前的寫法。
從這個流程可以發現,資料都是用XML傳遞,而且是在背景。而且傳遞的XML不見得會是自己定義的XML,你也可以直接傳遞畫面結果所需要的HTML(這也是XML啊),然後直接填到動態HTML物件如Div及Span。

    * Ajax時鐘-套件及配置

要在php上撰寫 Ajax,在這裡我介紹xajax函式庫。
xajax是一個以Server為主的Ajax函示庫,也就是說很多的商業邏輯將會放在Server Side的php程式裡。
此外還有另一套叫做Prototype的函示庫,他就是Client為主的,好處是在於就算把商業邏輯的Server端程式替換掉,也幾乎不會影響程式的運作(在這樣的設計模式下,Server Side有點像只是提供資料庫存取)。
接下來將一步一步地介紹如何撰寫Ajax模式的程式。

檔案及資料夾結構

下載xajax-0.2.4套件包並且解開,你會看到xajax.inc.php, xajaxCompress.php及xajaxResponse.inc.php,以及裝有xajax.js的xajax_js資料夾。

在Ajax時鐘的目錄下,將上面的檔案複製過去。順便先建立好檔案,做成這樣的配置
/ajaxclock/
/ajaxclock/index.php
/ajaxclock/clock.server.php
/ajaxclock/xajax/xajax.inc.php
/ajaxclock/xajax/xajaxCompress.php
/ajaxclock/xajax/xajaxResponse.inc.php
/ajaxclock/xajax_js/xajax.js

    * Ajax時鐘-ClientSide Code

Client Side的角色就是index.php,你也可以更名為clock.php,意思更明確。
這個程式的流程是:

   1. 建立Ajax物件,告訴他Server Side程式的檔名
   2. 註冊你要呼叫的Server Side副程式
   3. 在標籤的中間,呼叫Ajax物件的printJavascript(’./’);,參數是告訴他xajax_js目錄在哪

我在這裡註冊了兩個副程式,GetTime讓他每一次自動取得時間用的,ShowTime是來展示如何將表單資料送到Server Side程式。
在中間的body onload事件中,可以看到呼叫xajax的方式。如果你的註冊的副程式叫做GetTime,你就要用xajax_GetTime來呼叫。這裡我們在呼叫的時候並沒有傳入任何參數。配合JS的setTimeout,我們可以每一秒呼叫GetTime來更新。

你會問說,要更新的不是<input type=’text’ id=’text’>的文字盒嗎?怎麼沒有看到任何設定value=’幾點幾分’ 的程式碼呢?這個你就要接下去看ServerSide的程式碼了。先記著,我們要更新的物件,他的id是text。

我們會產生這樣的index.php:

<?php
require_once "xajax/xajax.inc.php";

$Ajax = new xajax("clock.server.php");
$Ajax->registerFunction('GetTime');
$Ajax->registerFunction('ShowTime');
?>

<!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>Ajax 時鐘</title>
<?php $Ajax->printJavascript('./'); ?>
</head>


<body onload="setInterval('xajax_GetTime()',1000)">
<form id="form1" name="form1" >
  現在的時間 :
  <input name="time" type="text" id="textbox" size="28" />
</form>
</body>
</html>

    * Ajax時鐘-ServerSide Code

這個程式的流程是這樣:

   1. 撰寫好你所需要的副程式
   2. 在主程式碼的部分,建立一個Ajax物件,也是同樣地告訴他ServerSide程式的檔名
   3. 同樣地註冊副程式
   4. 一定要呼叫processRequests()

那剛剛的GetTime從ClientSide被呼叫了,該怎樣去設定那個input id=’text’的值呢?

   1. 在副程式裡,建立xajaxResponse物件
   2. 呼叫他的addAssign,裡面傳入你要設定的

      ($id,$attribute,$value)

      。這裡的id可以是ClientSide的HTML中的任何一個物件的ID,例如說form1也可以(因為有<Form id=’form1′>這一行)。attribute這個是這個物件的屬性,這個你就要參考W3School HTML DOM Reference了。input應該有一個屬性叫做value,目的就是要設定該物件顯示的值,所以在這裡的第二個參數是value。第三個參數就是你要給他的值了,當然就是時間字串囉。
   3. 記得要將xajaxResponse物件回傳啊

如此我們會產生clock.server.php:

<?php
require_once "xajax/xajax.inc.php";
function GetTime()
{
    $response=new xajaxResponse();
    $response->addAssign("textbox","value",date('H:i:s'));
    return $response;
}
$Ajax=new xajax('clock.server.php');
$Ajax->registerFunction('GetTime');
$Ajax->registerFunction('ShowTime');
$Ajax->ProcessRequests();
?>

    * Ajax時鐘-表單的處理

由於Ajax不需要任何POST的動作,因此Form標籤裡就可以不用加上action和method屬性

我們先在index.php裡加上一行,

<input type="button" value="將值傳送到clock.server.php處理" onclick="xajax_ShowTime(xajax.getFormValues('form1'))"/>

因為不需要POST表單,所以type當然是button即可。在onlick事件中,我們呼叫了一個ShowTime副程式,等會一定要在 clock.server.php中宣告。為了要將表單form1中的任何變數都傳到ShowTime副程式,此時,xajax的JS物件就提供了 getFormValues的方法,並且要傳入表單的ID。如果你正常地配置了xajax.js,透過$Ajax-> printJavascript(’./’); 這一小斷程式碼便會將xajax物件包含進來,應該是可以不用擔心。

在clock.server.php中,我們加上

function ShowTime($arg)
{
    $response=new xajaxResponse();
    $response->addAlert(print_r($arg,true));
    return $response;   
}

如果前面的動作都正確的話,$arg就應該是一個hash,並且會有一個key叫做text,裡面包含值。
我們可以看到xajaxResponse提供一個功能讓你快速地在ClientSide呼叫警告對話盒,相當於呼叫window.alert()
此外他也提供另一個功能是addScript,讓你在ClientSide執行任何的JS。

這些你都可以參考Xajax的Wiki。

    * 除錯

除錯需要的是耐心,也是因為現有的Browser除錯的支援程度就是這樣而已。
你可以參考:
http://www.ruby.oss.tw/html/modu ... _id=87&forum=10

    * 比較和結論

優點
在上面的範例中,我們知道Ajax的優點,在於可以以背景的方式更新部分的畫面。這些畫面就是看設計者怎樣去配置HTML物件,xajax的函式庫也大幅地簡化了這個流程。這樣確實是以往php程式所做不到的,一旦在ClientSide使用自動或是半自動的將資料POST回php程式來取得結果,便會有很多不確定的因素,但又要為了效果而不得不做取捨。例如說有個表單需要驗證,如果驗證沒過便要顯示怎樣的訊息,在ASP.Net裡是有好用的控制項,他乾脆把驗證程式碼一起丟到ClientSide讓JS程式碼去做驗證。而寫php當然也可以如此(反而是應該要如此),如果不用這種方法,就得將資料 POST回去,造成每改一個字或是做個選擇,就會更新一次畫面。使用Ajax來做,不管是處理表單還是驗證都可以寫在ServerSide,充分解決 View及Control以往糾纏不情的情況。

缺點
Ajax也有為人詬病的問題,例如說資料量大,造成速度的問題。ajax需要將很多事情都用XML包裝,為了更新部分畫面,展示特效,往往消耗大量的頻寬,結果還是造成平均的網頁讀取時間低落。對於少量的資料,或是在短暫時間內更新極少部分,使用者不會有太大感覺。但是誇張一點的,像是微軟的電子地圖,或是Outlook WebAccess這個產品,還有這個模擬桌面的展示網頁,玩玩看就知道要付出多大速度的代價。這一方面相對於ajax方式,原來php一次就傳回結果,而不是分次載入,簡潔的結果和快速的反應,比較適合不需要炫麗效果,要求正確度的程式。

會遇到的問題
如同xajax函式庫一樣,所有撰寫的人都會遇到幾個問題。第一就是字碼,為了安全地使用HTTP傳送資料,資料必須經由HTML encode然後才送出。但是大部分的瀏覽器,在window.alert的時候,遇到html encode字串都不能解析。此外傳送的字串一定要是UTF8,如果其他的字串將造成不能解析。所以使用Dreamweaver中文版,或是其他預設不是 UTF8的編輯器,就要加倍小心,也不能夠在UTF8文件中加上BOM(UTF8 Signature),否則通常會造成Web Server不能讀取。

再來是除錯機制,xajax有還不錯的除錯機制,有任何不是正常的XML回應,都會顯示出來。官方也說明了可以利用Zend Studio來進行debug。其他的xajax函式庫就不是相當容易除錯的,大部分還是要靠設計師的毅力及直覺了。

結論
對PHP的程式設計師而言,能夠活用多種不同的技術是相當重要的,而不是將解決方式綁死在同一種技術上。可能不同的技術混雜在一起,也會增加程式碼維護的難度,不管如何設計者一定要三思。

TOP

發新話題