一、引言
如今,有相當多的Web應用程序,如Backpack,Blinksale和Gmail,都把資料庫技術與AJAX整合到一起。透過提供與資料庫通訊而不用刷新瀏覽器這種強大的技術,這種整合對web應用程式和使用者體驗產生巨大的影響-這意味著,在用戶繼續其它互動的同時可以實現即時的資料傳輸。
本文將集中討論上述技術整合機制。同時提供了完整的參考原始碼。這個範例是一個簡單的職務記錄應用程序,其中每個職務包含一個標題,描述和日期-允許使用者新增、編輯和刪除職務。所有這些都是你與資料庫記錄資料打交道時的基本操作,但是這個應用程式更進了一步。一個職位可以變化成一個可編輯的表單-它將被從資料庫中加以保存或刪除,以及以其新狀態顯示而不需要刷新瀏覽器併中斷用戶操作。
在本文中,我假定你已經初步了解AJAX、MySQL和PHP,或一類似的伺服器端語言。如果你還沒有建立過XML HTTP Request對象,那麼可以先參考我的文章「怎麼使用AJAX」。下面,首先讓我們討論資料庫的問題。
二、建立資料庫
你需要做的第一件事是建立資料庫表來為這些職務儲存資料。我創建了一個叫做informit_ajax的MySQL表-它擁有ID,title,description和date字段-這些都是在本文中不斷重複出現的變數。以下是建立此表的程式碼:
CREATE TABLE ′informit_ajax′ (
′id′ int(11) NOT NULL auto_increment,
′date′ datetime NOT NULL default '0000-00-00 00:00:00',
′description′ longtext NOT NULL,
′title′ varchar(100) NOT NULL default '',
PRIMARY KEY (′id′)
) TYPE=MyISAM;
你可以用任何MySQL查詢工具或開發應用程式所使用的語言來執行這段程式碼。一旦準備好資料庫,接下來就需要建立向PHP後台發出請求的前端檔案。
三、發出請求
這裡的索引HTML檔案是一簡單的資料佔位符-它將被從資料庫中加以分析。該檔案包含到JavaScript和CSS檔案的參考;還包含一個發出首次請求的onload處理器和三個div標籤:
· Layout-用於將頁面內容居中
· loading-在被請求的資料載入期間載入訊息,它將為HTTPRequest物件所接收
· posts-用於顯示每一個分析後的職務資料
<head>
<title>How to Integrate a Database with AJAX</title>
<link href="css/layout.css" rel="stylesheet" type="text/css" />
<script src="js/request.js"></script>
<script src="js/post.js"></script>
</head>
<body onload="javascript:makeRequest('services/post.php?method=get');">
<div id="layout" align="center">
<div id="posts"></div>
<p><input type="button" value="add a post" onmousedown="javascript:makeRequest('services/post.php?method=save');" /></p>
<p><div id="loading"></div></p>
</div>
</body>
當頁面裝載時產生第一個請求。這個請求發送一個get查詢到一個我們稍後會創建的PHP類別;但是首先我們需要為請求的回應建立分析方法。 JavaScript請求文件負責處理所有的基礎工作,例如建立對象,發送請求以及檢查準備狀態等。當從Request物件收到回應時,我用這個JavaScript職務檔案來處理這些職務的HTML生成。 onResponse方法是相當強壯的,因為它以文字和表單兩種版本處理每個職務的HTML頁面生成,並且把它們放置到它們自己定制的div標籤中;這樣以來,我們就可以容易地在用戶交互期間定位它們。透過這種方法,我們可以在每個職務的文字和表單版本之間進行切換-這可以透過點擊一個"edit this post"連結來實現。以下是針對每個職務所建立的HTML頁面的程式碼,你可以在本文對應的下載原始檔中看到完整的方法實作。
var html = "<div class='post' id='post_"+ i +"' "+ postDisplay +">"
+ "<div class='title' id='title_"+ i +"'>"+ _title +"</div>"
+ "<div class='description' id='description_"+ i +"'>"+ _description +"</div>"
+ "<div class='date' id='date_"+ i +"'>"+ _date +"</div>"
+ "<a href="javascript:toggle('"+ i +"');">edit this post</a><br/>"
+ "</div>"
+ "<div class='post' id='formPost_"+ i +"' "+ formPostDisplay +">"
+ "<div class='title'><input type='text' name='title' id='formTitle_"+ i +"' size='60' value='"+ _title +"'></div >"
+ "<div class='description'><textarea type='text' id='formDescription_"+ i +"' wrap='virtual' cols='60' rows='15'>"+ _description +"</ textarea></div>"
+ "<div class='date'>"+ _date +"</div>"
+ "<input type='button' name='cancel' value='cancel' onclick="javascript:toggle('"+ i +"');">"
+ "<input type='button' name='delete' value='delete this post' onclick="javascript:deletePost("+ _id +");">"
+ "<input type='button' name='submit' value='save this post' onclick="javascript:saveNewPost("+ _id +","+ i +");">"
+ "</div>"
+ "<p>"nbsp;</p>";
每個職務的文字版本簡單地顯示標題,描述和日期以及一個"edit this post"連結。每個職務的表單版本有三個按鈕:
·"cancel "按鈕-簡單地把職務的狀態切換回文字版本。
·"delete this post"按鈕- 把當前職務的ID發送給PHP物件以從資料庫中刪除它。
·"save this post"按鈕- 允許使用者把新的或編輯過的職務保存到伺服器
。方法把當前索引值提供給這些核心方法,這樣正確的職務就可以用基於該索引的正確資訊進行更新。描述與程式碼範例:
· 下面的saveNewPost方法透過收集並把表單輸入值傳送給PHP物件來儲存新的職務並且把getPost方法設定為onreadystatechange的回傳方法:
function saveNewPost(_id, _index){
var newDescription = document.getElementById("formDescription_"+ _index).value;
var newTitle = document.getElementById("formTitle_"+ _index).value;
setIndex(_index);
sendRequest("services/post.php?method=save"id="+ _id +""title="+ newTitle +""description="+ newDescription, getPost);
}
· 下面的getPost方法是一個回呼方法-它負責當從PHP物件收到回應時更新單獨的職務:
function getPost(){
if(checkReadyState(request)) {
var response = request.responseXML.documentElement;
var _title = response.getElementsByTagName('title')[getIndex()].firstChild.data;
var _description = response.getElementsByTagName('description')[getIndex()].firstChild.data;
var _date = response.getElementsByTagName('date')[getIndex()].firstChild.data;
document.getElementById("title_"+ getIndex()).innerHTML = _title;
document.getElementById("description_"+ getIndex()).innerHTML = _description;
document.getElementById("date_"+ getIndex()).innerHTML = _date;
toggle(getIndex());
}
}
· 下面的deletePost方法把目前索引作為一個請求傳送給PHP對象,這最終將刪除資料庫中的記錄並以更新的職務進行回應:
function deletePost(_id){
sendRequest("services/post.php?method=delete"id="+ _id, onResponse);
}
令人驚訝的是,最複雜的部分已經結束了。以下讓我們分析最關鍵的部分-資料庫互動。
四、與資料庫交互
為了實現與資料庫的交互,你需要創建方法用於檢索,插入,代替和刪除職務。我選擇建立一個post類,其中有get,save和delete方法來處理這些交互。這個類別還有一個到資料庫連接檔(用於連接到資料庫)的參考。你必須用自己的資料庫資訊來代替登錄,口令和資料庫名。
DEFINE ('DB_USER', 'USERNAME');
DEFINE ('DB_PASSWORD', 'PASSWORD');
DEFINE ('DB_HOST', 'localhost');
DEFINE ('DB_NAME', 'DATABASE');
$dbc = @mysql_connect (DB_HOST, DB_USER, DB_PASSWORD) OR die ('Could not connect to MySQL: ' . mysql_error() );
到連接檔案的參考以及資料庫的名字位於該類別的建構器中。你的構造器看起來應該跟下面程式碼相似:
function Post(){
require_once('mysql_connect.php');
$this->table = "informit_ajax";
}
下面的dbConnect方法負責建立連線-透過將登入資訊傳送給資料庫;這個方法被重用於查詢資料庫前的所有核心方法:
function dbConnect(){
DEFINE ('LINK', mysql_connect (DB_HOST, DB_USER, DB_PASSWORD));
}
下面的get方法循環遍歷資料庫表,它基於資料庫行建立一個XML字串,並把該字串傳回給請求者:
function get(){
$this->dbConnect();
$query = "SELECT * FROM $this->table ORDER BY id";
$result = mysql_db_query (DB_NAME, $query, LINK);
$xml = "<?xml version="1.0" encoding="ISO-8859-1" ?>n";
$xml .= "<posts>n";
while($row = mysql_fetch_array($result)) {
$xml .= "<post>n";
$xml .= "<id>" . $row['id'] . "</id>n";
$xml .= "<date>" . $row['date'] . "</date>n";
$xml .= "<title><![CDATA[" . $row['title'] . "]]></title>n";
$xml .= "<description><![CDATA[" . $row['description'] . "]]></description>n";
$xml .= "</post>n";
}
$xml .= "</posts>";
mysql_close();
header("Content-Type: application/xml; charset=UTF-8");
echo $xml;
}
下面的save方法透過處理更新和插入位置來實現兩個目的:
function save($id, $title, $description){
$this->dbConnect();
$query = "SELECT * FROM $this->table WHERE id='$id'";
$result = @mysql_query ($query);
if (mysql_num_rows($result) > 0)
{
$query = "UPDATE $this->table SET title='$title', description='$description', date=NOW() WHERE id='$id'";
$result = @mysql_query($query);
}
else
{
$query = "INSERT INTO $this->table (title, description, date) VALUES ('$title', '$description', NOW())";
$result = @mysql_query($query);
}
mysql_close();
$this->get();
}
下面的delete方法負責刪除一個基於被當作參數傳遞的ID的位置。然後呼叫get方法來把新的資料回傳到請求檔:
function delete($id){
$this->dbConnect();
$query = "DELETE FROM $this->table WHERE id='$id'";
$result = @mysql_query($query);
mysql_close();
$this->get();
}
五、綜合應用程式
為了把以上各部分整合到一起,需要創建一個簡單的檔案來承擔XML HTTP請求和PHP物件之間的通訊橋樑。這時的頁面不僅創建PHP對象,還接收查詢並把變數傳遞給動態生成的方法-在此是指get,save或delete。下面的一個範例查詢包括了一個$method和可靠的$id,$title和$description變數。
require_once("../classes/Post.class.php");
$post = new Post();
$post->$method($id, $title, $description);
以後我們還會更進一步討論這些技術。如今的web開發看起來又變得年輕又充滿活力,而我們也很幸運地成為這個新科技時代的一部分。