中場一:資料庫連接
前兩章中集中介紹了PHP語言,現在停下來開始建立一個應用程式。在本章中將建立一個串連MySQL資料庫的應用程式。
在學習過前面兩章之後,你肯定已經學會了怎樣處理PHP內部資料,以及怎樣編寫語句和函數。下一步從邏輯上講,應該到了學習如何用SQL(結構化查詢語句)處理PHP的外部資料的時候了。但是,在開始學習這部分內容前,讓我們暫時中斷基本原理的學習,放鬆一下。
讓我帶你一道探究PHP應用程式的開發曆程。從字面意義上講,每一個應用程式都應該是獨特的,但是每一個應用程式也都能在此前的工作基礎上,即一系列通用功能的基礎上構建。我建議將這兩項技術混合在一起。盲目地使用前人已編寫好的功能,會剝奪在程式中加入新特色,還會阻止為提高函數的效率而去修改舊函數。從另一方面講,使用已有函數意味著能更快的開發出應用程式。所以必須在這兩個極端中把握好自己,才能成為一個優秀的程式設計員。
注意:如果現在還對HTML不熟悉,那麼現在就是開始學習的時間了。本書中假定你已經熟悉HTML了。如果還不熟悉HTML表格和表單的話,很快就會被搞糊塗的。
5.1 開端
每當開始一個新項目時,我喜歡從一個新的空目錄開始。在這裡,讓我們把這個目錄稱為phpbook/ch05。當然,這個目錄必須在Web伺服器的根目錄下。如果你是按照第一章的指令安裝PHP的話,那麼,Web伺服器的根目錄就應該為/usr/local/apache/htdocs。接著,我們將建立一個名為menu.php3的檔案,其中包含有一個後台管理工作菜單,如清單5.1所示。
清單5.1 menu.php3
Administrative Menu
- Creat Database
Connection
在檔案common.inc中包含對函數affy_header和affy_footer的定義。這些函數在本章中稍後還會出現。
5.2 建立串連
當點擊Create Database Connect(建立資料庫連接)聯結時,將會執行connect.php3檔案,該檔案將嘗試串連在第二章學習中安裝的MySQL資料庫伺服器。
清單5.2 顯示了connect.php3檔案使用使用者名稱codebits和密碼codebits嘗試進行資料庫連接,因為在安裝MySQL時還沒有建立該使用者名稱,所以串連肯定失敗。然而失敗 -- 最起碼在本例中 -- 卻是一件好事,因為我們可以看看應該如何處理這個問題。圖5.1給出了串連失敗後將會顯示的錯誤資訊和表單。
清單5.2 connect.php3
Page 107 -108 清單 5.2
Page 108 Figure 5.1
圖5.1 串連失敗時的錯誤資訊顯示
當資料庫連接失敗時,程式會給出一個錯誤資訊提示和一個表單,使用者可以在裡面輸入root使用者的密碼。就像在本章稍後講的那樣,有了root的密碼,就可以建立名為codebits的使用者。現在先跳過有關$arr_request數組的部分。
當函數mysql_connect被調用且串連失敗時,該函數通常會顯示如下資訊:
Warnint: MySQL connection Failed: Access denied
for user: 'codebits@localhost' (Using password: YES)
絕大多數應用程式需要精確的控制顯示的內容,尤其是高度圖形化的應用程式。在函數mysql_connect前加上(@)符號將會抑制錯誤資訊的顯示。
注意表單語句的action屬性指定點擊submit按鈕時,將會執行connect.php3檔案。這是一個遞迴程式的例子,也就是說允許PHP檔案調用它自己。
應用遞迴編程技術,可以將有關同一個主題的所有代碼編製在同一個檔案中。至於什麼時候應該將函數組合成一個檔案,或將程式分解成幾個檔案,這得憑經驗。我的首要原則是:當實現一個特定功能所編的程式碼超過100行以上時,就要建立一個獨立的檔案。
5.3 擷取HTML表單資訊
即使輸入一個密碼並點擊串連資料庫,串連仍然會失敗,原因是connect.php3還沒有使用表單中的輸入值去建立資料庫連接。
PHP引擎將每一個表單域放到一個叫做$HTTP_POST_VARS的數組中。在上述給出的例子中,數組有兩個元素:username和password。在此程式中可以通過$HTTP_POST_VARS['username']和$HTTP_POST_VARS['password']訪問表單資訊。
使用$HTTP_POST_VARS['password']獲得表單中的資訊看起來比較簡單。但是仍有一些隱藏的問題。首先,要檢查表單域的名字(本例中的password)是大寫、小寫、還是大小寫都有。
第二件問題包含的內容與本例關係不大。除了表單方法以外,還可以使用URL來運行PHP指令碼,例如:
http://.../connect.php3?username=root&password=password
可以看到,使用者名稱和密碼通過URL進行傳遞,問號“?”標誌著域資訊的開始,“&”則是域的定界符。幸運的是,PHP引擎也自動分析URL行,並將結果存入$HTTP_GET_VARS數組中。
問題(如果你認為它是的話)在於,程式可以從不止一個地方獲得資訊 -- 數組$HTTP_GET_VARS和數組 $HTTP_POST_VARS。
對待這些(或其它一些的)問題,我的解決辦法是建立一個名為$arr_request的數組,它從兩個$HTTP數組中獲得初始化的資訊。在common.inc中可以使用如下編碼行對數組$arr_repuest進行數值初始化。
// declare the request array which holds both
// url-based (get) and form-based (post) parameters.
$arr_request = array();
// move the url and form parameters into the
// request array. Form parameters supercede url
// parameters. Additionally, all keys are vonverted
// to lower-case.
If (count($HTTP_GET-VARS)) {
While (list($key, $value) = each ($HTTP_GET_VARS)) {
$arr_request[strtolower($key)] = $value;
}
}
if (count($HTTP_POST_VARS)) {
while (list($key, $value) = each ($HTTP_POST_VARS)) {
$arr_request[strtolower($key)] = $value;
}
}
如果在所有的PHP指令碼中都包含有common.inc檔案的話,那麼不用擔心指令碼是怎麼啟動並執行。所有傳過去的資訊都以小寫形式儲存在數組$arr_request中,這就意味著,可以使用$arr_request['username']得到使用者名稱資訊。
PHP提供了數組$HTTP_GET_VARS和數組$HTTP_POST_VARS的替代方式,HTML表單和基於URL的資訊都可以直接做為PHP變數進行訪問。例如,在PHP 指令碼中,一個定義為的域資訊可以直接在PHP程式中用$last_name訪問,同樣的基於URL的資訊,比方說,http://www.site.com?last_name=join,能由$last_name獲得。不過,我還是比較喜歡使用數組$arr_request,因為對於要迴圈使用傳遞給程式的所有資訊來講,這是非常有用的。如果該資訊是一個標量,那麼它就不適合被迴圈使用。例如:將所有參數名改為大寫,以保證不致於因為使用換檔鍵而破壞程式;或者在錯誤偵測時,會需要顯示所有的輸入參數。
注意:本節只對CGI(通用閘道介面)協議作很簡單的介紹,更詳細的內容請參閱本書附錄A,“網際網路資源”中所列內容。
5.4 使用HTML表單資訊
既然可以很容易地從PHP指令碼程式中存取表單資訊,現在是利用這些資訊串連資料庫的時間了。第一步是檢查串連資料庫的代碼:
$id_link = @mysql_connect('localhost', 'affy', 'affy');
在這行代碼中,使用者名稱和密碼都是字串數值。為了能利用表單中的資訊,這行代碼需要加以變動,用變數代替數值:
$id_link = @mysql_connect(
'localhost',
$username,
$password);
既然用到了變數,那麼必須對變數進行初始化。以下代碼將執行這種初始化:
if ( count($arr_request) ) {
$username = $arr_request['username'];
$password = $arr_request['password'];
}
else {
$username = 'phpuser';
$password = 'phpuser';
}
當表單資訊可用時,函數count的結果將大於1,使得if語句執行真條件的子句,此子句依次從$arr_request數組中取出使用者名稱和密碼資訊。
當沒有表單資訊存在時,使用者名稱和密碼仍可以用字串數值進行初始化。
第三種可能性是一個表單有這兩個域但沒有表單資訊。如果調用connect.php3的表單沒有username和password域,會發生什麼情況呢?如果這樣,以上代碼將失敗。通過直接檢查表單欄位,而不是只依賴於$arr_request數組的元素數目可以讓這段代碼的更強壯(即,能處理這種環境下的失敗)。例如:
$username = $arr_request['username'];
$password = $arr_request['password'];
if (empty($username)) $username = 'phpuser';
if (empty($password)) $password = 'phpuser';
因為PHP對沒有初始化的數組元素將返回Null 字元串,以上代碼的適應性將更強。使用標量比使用數組可以使代碼更容易理解,並且在某些方面更有效率。如果這兩個變數有一個為空白時,這意味著表單沒有提供任何值,將使用預設值。
清單5.3顯示了有以上更改的connect.php3檔案,可以在上下文看到這兩個變化的描述。
清單5.3 connect.php3修訂版
Page 112 - 113 清單 5.3
當正確的root密碼5.2所示被輸入到表單時,將會成功地建立資料庫連接。
Page 113, Figure 5.2
圖5.2 證實成功地建立了資料庫連接
5.5 common.inc檔案
清單5.4顯示了本章需要的common.inc檔案的版本。
清單5.4 common.inc--多個應用程式使用的一套常式。
function affy_footer() {
echo '';
}
function affy_header($title) {
echo ''; <br>echo "$title"; <br>echo '';
}
function affy_message($msg) {
echo '
'; echo '
'; echo "$msg"; echo ' |
'; echo '
';
}
?>
5.6 總結
本章介紹了如何使用PHP串連資料庫,第一步建立了一個Web菜單頁,用它可以運行串連資料庫的指令碼,然後建立了可以串連資料庫的connect.php3檔案。
當connect.php3檔案使用affy使用者名稱企圖串連資料庫時失敗了,從而導致顯示出了需要root使用者密碼的表單。
表單中的資訊通過common.inc檔案被放在$arr_request數組中。並修改了connect.php3檔案,使其使用變數$arr_request中的使用者名稱和密碼來串連資料庫。