使用jQuery和PHP構建一個受Ajax驅動的Web頁面
大多數 PHP 開發人員都是以老式的方法學習技能。他們一般先學習如何定義和構建簡單的 PHP 頁面,然后再了解如何將這些頁面連接到簡單的 MySQL 表,于是就可以由此進行自己的開發了。隨著技能水平的提高,他們還逐漸學會了如何創建更為復雜的 PHP 功能,以及如何連接 MySQL 內的表并執行其他高級任務。
在這個過程中,他們有可能還會掌握一些客戶端技能來將 Web 應用程序投入使用。也有可能學會有關 XHTML 或 CSS 甚至一些 JavaScript 編程的知識。隨著所參與項目的種類的增多,他們甚至有機會接觸到 Ajax 以便為您的 Web 應用程序賦予 Web 2.0 或 “桌面” 的感覺。不過,如果您初次使用 Ajax 的經驗與我類似的話,您可能已經做了太多的工作 — 手動實現各種函數、經歷創建一個受 Ajax 驅動頁面的艱難過程。
對于某些人而言,Ajax 仍是個謎。它似乎是 Web 開發/交互社區中的 “酷小孩(cool kid)” 和 “壞小孩(bad boys)” 才會做的事情,而他們則沒有時間和耐心或者能力去了解并使用它。這真是個遺憾,因為很多客戶的確喜歡添加 Ajax 風格的功能 — 它讓 Web 應用程序更容易使用。如果您是這些 PHP 開發人員中的一員,也請不要害怕:讀完本文,您所掌握的知識足以讓您成為一名真正的 Ajax 專業人士。
本文展示了如何使用 jQuery 來向 PHP Web 應用程序輕松添加 Ajax 功能。我們將使用 PHP 和 MySQL 構建一個簡單的 Web 應用程序 — 一個包含名字和電話號碼的電話本。這個應用程序具備預期的所有標準功能 — 比如可以查找名字或電話號碼、具有 MySQL 表等。接下來,還將向應用程序添加 jQuery,以便能夠在鍵入時實時查找名字和電話號碼。在完成上述任務后,您也就具備了有關 jQuery 及 Ajax 的充足的基礎知識。
何為 Ajax?
描述 Ajax 的最佳方法是將其與傳統方式進行對比。大多數 Web 頁面和應用程序都在同步模式下工作。單擊一個鏈接或表單的提交 按鈕后,請求就被發送給服務器,而此服務器之后會處理該請求并發送回一個響應。總結此模型的最好方法是 “單擊、等候、查看”。這就是您所熟知的一個永不終止的漂洗-和-重復(rinse-and-repeat)的循環過程。換言之,如果頁面需要經常顯示被更新的信息,那么就必須放上某類自動刷新 hack,或者是讓用戶刷新或單擊一個鏈接執行刷新。
Ajax 改變了這一切。Ajax 中的第一個字母 A 代表的是 異步。Ajax 允許以任何一種編程語言創建頁面,然后用來自數據庫或其他后端服務器過程的信息刷新該頁面的不同部分。比如,假如說您有一個電子商務站點,上面顯示了所銷售的產品。在每個產品頁面,都有幾個常見項目:標題、銷售說明、縮略圖圖片、庫存數量。
假如,您想讓網站的訪問者能夠獲得庫存數量的最新信息。您就可以添加一個 Ajax 函數,該函數能運行包含 MySQL 查詢的一個單獨的 PHP 頁面,然后就可重新填充原始頁面上的信息,無需用戶輸入,也不必考慮事件的單擊-等待-查看模式的同步性。
Ajax 中的 j 代表的是 JavaScript,它是所有行為的驅動力。這既是好事也是壞事 — 好的一面是由于是客戶端代碼,所以它是可移植的,而且不會影響到服務器;對 PHP 開發人員而言不好的一面是它完全不同于他們所習慣使用的那個環境。這就需要像 jQuery 這樣的工具和框架來大大簡化您與 Ajax 交互的方式,加快代碼完成的進度。
最后的兩項:+ 和 x 又代表什么呢?它們代表的是 及 XML,不過,XML 部分并不確切。大量 Ajax 應用程序在沒有任何 XML 代碼時仍工作得很好:它們只來回傳遞 HTML,甚至是純文本。更準確的說法是讓 x 代表 XMLHttpRequest,因為可使用該對象在后臺檢索數據,而不會干擾現有頁面的顯示或行為。
何為 jQuery?
jQuery 是 John Resig 創建的一種輕量的 JavaScript 庫,在 2006 年早期發布于 Internet。它是免費的開源軟件,具有 Massachusetts Institute of Technology (MIT) 和 GNU General Public License 的雙重許可。由于它簡單直觀,因此贏得了開發界很多人的擁護。
那么它為何如此流行呢?因為它提供了一種簡單易用的庫,簡化了 JavaScript,因此任何人(沒錯,甚至一個徹徹底底的后端程序員)無需艱苦的工作就能創建非凡的效果。您可以進行 Document Object Model (DOM) 元素選擇、修改和處理 CSS、使元素更加吸引人以及處理 Ajax。所有這些功能性的實現都來自于一個 JavaScript 文件,該文件可從 jQuery 站點下載(參見 參考資料)。
下載 jQuery 之后,通過包括進一個簡單的 ﹤script﹥ 標記就可以將其添加到任何的 HTML 或 PHP 文件:
﹤script type="text/javascript" src="/path/to/jquery.js"﹥﹤/script﹥ |
假設,您有一個非常簡單卻很煩人的任務要完成 — 需要很多手動操作,比如在您站點上的每個表單標簽末尾添加一個冒號(:)。您可以遍歷并尋找每個表單標簽并在每行的末尾添加一個冒號,您也可以部署如下的 jQuery 代碼:
清單 1. 使用 jQuery 添加一個冒號
﹤script type="text/javascript"﹥ $(document).ready(function(){ $("label").append(":"); }); ﹤/script﹥ |
此函數很簡單:它將一直等待,直到頁面準備好并全部加載($(document).ready() 部分)完畢,這時將運行一個匿名函數,該函數尋找所有 DOM label 元素,然后向所找到的文本的末尾追加一個冒號。$() 函數的功能是允許以其本地名字訪問 DOM 元素,這就讓此接口成為了已經熟悉 DOM 的那些開發人員的最佳選擇。
當然,用 jQuery 還能做很多其他的事情,這只是一個好的開端。借助一個簡單的內置函數,jQuery 可以確保您的代碼能夠工作,因為它會等待頁面加載。有了另一行代碼,就能對代碼所找到的所有 DOM label 元素進行徹底更改,所有都在客戶機內進行,而無需乏味地遍歷所有標記并在那里進行更改。
#p#
創建一個簡單的應用程序:一個電話本
有了 jQuery 的基本知識之后,我們就可以開始用 PHP 和 MySQL 構建一個簡單的電話本應用程序了。這個應用程序包含三個部分:
◆一個 MySQL 表,用來保存人名和電話號碼
◆具有搜索表單的 index.php 文件
◆用來查詢數據庫表的 find.php 頁面
我們將依次構建這些元素。
創建數據庫表
在 MySQL 內創建數據庫表可能是最簡單的部分。我們希望此應用程序是一個包含有最少量信息的表 — 比如,一個 ID(表的鍵)、一個名字字段以及一個電話號碼字段。最后這兩個字段可以是字母數字,所以將使用 varchar() 函數。我們將創建 ID 字段作為一個 autoincrement primary key。將此表稱為目錄 并使用如下的 Structured Query Language (SQL) 代碼來創建它:
清單 2. 使用 SQL 創建目錄表
CREATE TABLE `directory` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR( 64 ) NOT NULL , `phone` VARCHAR( 16 ) NOT NULL , PRIMARY KEY ( `id` ) ) TYPE = MYISAM ; |
正如您所見,這里沒有什么復雜的。實際上,之后您將有大量機會自己更新這個應用程序。擴展此應用程序的一種方式是添加一個關鍵字或地址字段,而二者均能讓您進一步精煉搜索。不過,現在,我們還是先從簡單的開始吧。
創建了該表之后,需要填充它。可以使用 phpMyAdmin 或命令行來輸入一個名字和電話號碼。也可以使用如下的 SQL 指令集:
清單 3. 使用 SQL 填充此表
insert into `directory` (name,phone) values ('Tom Smith', '512-555-0111'); insert into `directory` (name,phone) values ('Bill Smith', '512-555-0112'); insert into `directory` (name,phone) values ('John Smith', '512-555-0113'); insert into `directory` (name,phone) values ('Jane Smith', '512-555-0114'); insert into `directory` (name,phone) values ('Sara Smith', '512-555-0115'); |
輸入了這些值之后,如果從命令行的目錄操作運行一個 select * 或單擊 phpMyAdmin 內的 Browse ,請確保能夠獲得一個記錄列表。
創建 index.php 文件
接下來,為應用程序創建一個簡單的主頁。此頁面是一個 PHP 文件,稱為 index.php,但此時它包含最多的仍是 HTML 代碼。當完成了 find.php 文件后(下一步),我們還會返回來完成這一代碼塊。
此刻,所需做的就是創建一個包含表單的骨架 HTML 文件。表單內的每個元素均包含一個惟一的 ID,因為我們想要能夠使用 jQuery 標識每一塊。
清單 4. 包含表單的 HTML 文件
﹤html﹥ ﹤head﹥ ﹤title﹥Welcome!﹤/title﹥ ﹤/head﹥ ﹤body﹥ ﹤h1﹥Search our Phone Directory﹤/h1﹥ ﹤form id="searchform" method="post"﹥ ﹤div﹥ ﹤label for="search_term"﹥Search name/phone﹤/label﹥ ﹤input type="text" name="search_term" id="search_term" /﹥ ﹤input type="submit" value="search" id="search_button" /﹥ ﹤/div﹥ ﹤/form﹥ ﹤div id="search_results"﹥﹤/div﹥ ﹤/body﹥ ﹤/html﹥ |
上述代碼中有兩點應該會立即引起您的注意。其一,沒有動作與此表單相關聯。這沒關系:請記住,此表單將不會遵循傳統的 “單擊、等待、查看” 的同步模式。相反,我們將會添加能夠監視 search_term 字段內的用戶動作的功能。
應該注意到的第二點是 search_results DOM 元素 — 表單下面的空白元素。這個 DOM 元素將會包含從搜索中獲得的所有響應。在對此進行深入研究之前,讓我們先來創建 find.php 頁面。
#p#
創建 find.php 文件
find.php 文件是所有操作發生的地方。在此文件內,應用程序連接到數據庫并針對此目錄表運行查詢。
find.php 文件的第一部分包含連接信息。出于本文的目的考慮,我將該信息嵌入到了此文件。對于大多數開發人員而言,此信息將會處于一個附帶的或必需的文件內,或是作為一個更大的框架的一部分。
清單 5. 創建 find.php 文件
﹤?php define(HOST, "your.host.here"); define(USER, "your-user-name"); define(PW, "your-password"); define(DB, "your-db-name"); $connect = mysql_connect(HOST,USER,PW) or die('Could not connect to mysql server.' ); mysql_select_db(DB, $connect) or die('Could not select database.'); |
接下來,將會從此 index.php 文件內的表單獲得一個搜索詞。對該搜索詞進行一些簡單處理,然后將該值插入到數據庫內。我選擇使用 strip_tags() 和 substr() 函數來刪除搜索詞內的所有 HTML 標記并對之進行簡化。進行這類預處理不失為一個好的做法 — 不能百分之百相信用戶的輸入。
實際上,當具有了一個清晰的搜索詞后,就可以通過 mysql_escape_string() 運行它,這可進一步消除可能會破壞數據庫的其他陷阱(比如,單引號)。
$term = strip_tags(substr($_POST['search_term'],0, 100));
$term = mysql_escape_string($term);
現在,構建 SQL 語句。我們希望從此目錄表能夠檢索到匹配搜索詞的所有名字和電話號碼。使用 LIKE 讓搜索詞能匹配名字和電話這兩個字段,然后使用 mysql_query() 運行此查詢。
清單 6. 構建 SQL 語句
$sql = "select name,phone from directory where name like '%$term%' or phone like '%$term%' order by name asc"; $result = mysql_query($sql); |
運行了此查詢后,可以打印結果。初始化一個 $string 變量來保存結果,然后使用 mysql_num_rows() 檢查是否得到了任何結果。如果沒有獲得針對此搜索詞的結果,可以將 $string 設置為等于 “No matches!”。如果的確獲得了結果,可打印結果集內的每個名字和電話號碼。在過程的末尾,使用 echo 命令打印整個字符串:
清單 7. 使用 echo 命令打印字符串
$string = ''; if (mysql_num_rows($result) ﹥ 0){ while($row = mysql_fetch_object($result)){ $string .= "﹤b﹥".$row-﹥name."﹤/b﹥ - "; $string .= $row-﹥phone."﹤/a﹥"; $string .= "﹤br/﹥\n"; } }else{ $string = "No matches!"; } echo $string; ?﹥ |
當然,這個 PHP 功能本身就十分有用,但是現在,這一點沒有突出體現出來。需要能夠為此腳本提供一個搜索詞。在下一節,我們將實現這一目的。
向 index.php 添加 jQuery
至此,我們得到的是一對普通的 PHP 頁面和一個簡單的 MySQL 表。當添加了 jQuery 后,這個普通的應用程序就會變成一個新穎的、受 Ajax 驅動的應用程序,它將更類似于 Mac OS X 上的 Spotlight 或 Google Desktop Search 這樣的桌面搜索應用程序。
現在,打開 index.php 文件并確保添加了對最新下載的 jquery.js 文件的調用。
﹤script src="./jquery.js"﹥﹤/script﹥
接下來,創建一個簡單的函數來阻止搜索表單表現得像典型的表單那樣。(使用 preventDefault() 函數實現此目的)。將所有 Submit 按鈕和 key-up 事件(即在通過鍵盤鍵入字符時發生的事件)重新指向到一個將要創建的新函數,稱為 ajax_search()。
清單 8. 創建函數以阻止搜索表單表現得像典型的表單那樣
﹤script type='text/javascript'﹥ $(document).ready(function(){ $("#search_results").slideUp(); $("#search_button").click(function(e){ e.preventDefault(); ajax_search(); }); $("#search_term").keyup(function(e){ e.preventDefault(); ajax_search(); }); }); |
您注意到我們是如何使用 slideUp() 函數來暫時隱藏 search_results DOM 元素的嗎?以及又是如何使用 $() 函數來按名字引用該 DOM 元素?如果您十分熟悉 CSS,那么 jQuery 方式就十分直觀和自然了。比如,假設有一個具有惟一 ID search_results 的 DOM 元素,您就可以使用 $("#search_results") 來引用它。就這么簡單。
另外還注意到,任何時候,任何人單擊了 Search 或在 search_term 字段鍵入一個字符,一個匿名函數都會阻止默認行為的發生并會將 應用程序流程重新指向到 ajax_search() 函數,該函數我們接下來將會構建。
ajax_search() 函數十分簡單。我們想要顯示 DOM 元素 search_results(之前已經將其隱藏)、獲得 search_term 輸入字段的值、將該值傳遞給一個異步運行 find.php 文件的函數($.post()),然后等待響應。當響應到來后(還記得么,我們已經確保了該 find.php 將會返回某種響應,即便在沒有匹配的情況下也是如此),jQuery 用該響應填充 search_results DOM 元素。
清單 9. ajax_search() 函數
function ajax_search(){ $("#search_results").show(); var search_val=$("#search_term").val(); $.post("./find.php", {search_term : search_val}, function(data){ if (data.length﹥0){ $("#search_results").html(data); } }) } ﹤/script﹥ |
所有系統都就緒后,就可以鍵入一個請求并查看此搜索引擎的實際工作情況了,每個 key-up 事件都會處理記錄。它在單擊 Submit 時也能工作。比如,在圖 1 中,如果在搜索字段內鍵入字母 a,應用程序就會返回 Jane 和 Sara Smith 這兩條記錄,因為這兩個名字中都包含此字母。
圖 1. 運行中的受 Ajax 驅動的搜索
結束語
當然,針對此應用程序還有很多工作可做。比如,可以添加一個關鍵字字段,然后允許按關鍵字搜索?;蛘?,可以讓每個人的記錄包含針對其所擅長的不同領域的標記或關鍵字。此后,如果您在項目中遇到問題,就能夠通過資源查找來找到能夠幫助您的人。此外,還可以添加一個電子郵件字段、一個生日字段 — 無論什么都可以 — 然后擴展搜索參數。
關鍵的一點是此應用程序的 jQuery 部分并不關心在后端發生的事情。它所知道的就是將一個搜索詞傳遞給一個稱為 find.php 的文件。find.php 文件并不知道也不關心它從一個 jQuery 函數接收指令。它所關注的是只要搜索詞來自于一個正常的表單提交過程,它就使用該數據來完成查詢,然后返回匹配該搜索詞的那些記錄。
【編輯推薦】