明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

用PHP與MySQL構建一個數據庫驅動的網站(6)

[摘要]摘要  在這一章內我們會學習到如何在一個Web頁面中向數據庫中存儲信息并顯示它。(2002-08-29 14:11:25)--------------------------------------------------------------------------------By Wing,...
摘要

  在這一章內我們會學習到如何在一個Web頁面中向數據庫中存儲信息并顯示它。

(2002-08-29 14:11:25)

--------------------------------------------------------------------------------
By Wing, 出處:Linuxaid


第四章: 用PHP訪問MySQL數據庫

  在這一章內我們會學習到如何在一個Web頁面中向數據庫中存儲信息并顯示它。之前我們已經安裝了MySQL這個關系型數據庫引擎以及PHP這個服務器端腳本語言,并學習了有關它們的基本知識。在學完這一章后,我們將明白如何綜合利用這兩個新的工具來構建一個數據庫驅動的網站!

對前一部分的回顧

  在我們往下繼續(xù)之前,回顧一下我們學習的目的應該是件有價值的事,F在有我們的系統(tǒng)中有了兩個強有力的新的工具:腳本語言PHP和數據庫引擎MySQL。搞清楚兩者是如果協同工作是很重要的。

  數據庫驅動的網站的實質就是允許站點的內容存在于一個數據庫中,并且可以通過這個數據庫來動態(tài)地產生Web頁面來讓我們的訪問者通過標準的Web瀏覽器來顯示它。所以在你的系統(tǒng)的一端是一個訪問你的站點的瀏覽者,他通過訪問http://www.yoursite.com/來獲得一個標準的HTML格式的Web頁面并在Web瀏覽器中顯示它。在你的系統(tǒng)的另一端是通過一個或幾個數據表存儲在一個只理解如何響應SQL查詢(命令)的MySQL數據庫中的你的站點的內容。

  PHP腳本語言承擔了兩者之間的聯絡員的角色,使用PHP,你可以編寫一個標準HTML的“模板”,這個“模板”決定了你的站點的外觀(包括圖畫和頁面設計)。這時內容是屬于這個“模板”的,你可以使用一些PHP代碼來連接MySQL數據庫并且使用SQL查詢來獲得數據并在其相應位置顯示它,這里的SQL查詢是和我們在第二章中用來建立笑話數據表時一樣的。

  現在對于訪問者在訪問你的數據庫驅動的網站的一個頁面時,到底會發(fā)生什么事,你應該有個明確的認識了:

  訪問者的Web瀏覽器使用一個標準的URL請求這個頁面。

  Web服務器軟件(Apache、IIS或其他)認定被請求的頁面是一個PHP腳本,因而在響應這個頁面請求之前用它的PHP插件來解釋它。

  一些PHP命令(我們還沒學到)會連接MySQL數據庫并向數據庫請求屬于這個Web頁面的內容。

  MySQL數據庫作出響應并且向PHP腳本發(fā)出被請求的內容。

  PHP腳本將內容存儲到一個或幾個PHP變量中,并使用我們熟悉的echo函數將其作為Web頁面的一部分輸出。

  PHP插件完成處理并將生成的HTML副本返回到Web服務器。

  Web服務器將這個HTML副本發(fā)送到Web瀏覽器,這將是一個標準的HTML文件,只不過它不是直接來自于一個HTML文件,而是來自于PHP插件提供的輸出。

用PHP連接MySQL

  在我們從我們的MySQL數據庫中獲取我們的Web頁面所包含的內容之前,我們首先必須知道如何建立與MySQL的連接。在第二章中,我們使用了一個叫mysql的程序來做這樣的連接。PHP不需要這樣的一個程序,對連接MySQL的支持是語言內置的。下面的這個函數用來建立這樣的連接:

mysql_connect(<address>, <username>, <password>);


  在這里,<address>是MySQL服務軟件在其上運行的計算機的IP地址或主機名(如果這與運行Web服務軟件的計算機是同一臺,你可以使用"localhost"),<username>和<password>就是你在第二章中用來連接到MySQL服務器的用戶名及口令。

  你可能還記得PHP中的函數在被調用時往往會返回(輸出)一個值。請不要擔心我們沒有提醒你,我們在最初接觸一個函數時都會為你詳細詳細它。絕大多數的函數在被調用后,都會返回一個可以在存儲在變量中的值以備下次使用。例如我們上面介紹的mysql_connect函數,會返回一個數字來標識已經建立的連接。因為我們會要使用這個連接,所以我們必須保存這個值。下面是一個關于如何連接我們的MySQL數據庫的一個實例:

$dbcnx = mysql_connect("localhost", "root", "mypasswd");


  需要說明的是,對于你的MySQL服務器,上面這個函數中的三個參數的值可能是不同的。你應該注意到在這兒我們的mysql_connect 返回了一個值(我們稱之為一個連接標識),這個值被我們存儲在變量$dbcnx中。

  因為MySQL是一個完全分布式的軟件,我們必須考慮到這些可能性:服務不可用、網絡堵塞或者是我們的用戶名及口令不匹配。在這些情況下,mysql_connect函數不能返回一個連接標識(因為連接未被建立)。這時,會返回一個邏輯假。這使得我們可以用一個if語句來處理連接的情況: $dbcnx = @mysql_connect("localhost", "root", "mypasswd");


if (!$dbcnx) {
echo( "<P>Unable to connect to the " .
"database server at this time.</P>" );
exit();
}



  在上面的代碼段中出現了三個新的東西,首先,我們在mysql_connect函數前加了一個@符號。包括mysql_connect在內的許多函數會在失敗后顯示難看的錯誤信息。在函數名前加一個@符號可以告訴這個函數當執(zhí)行失敗時,允許我們顯示我們自己友好的出錯信息。

  其次,在我們的if語句的條件中,$dbcnx變量前面加了一個驚嘆號。這個驚嘆號是PHP中的“否運算符”。也就是說將邏輯真變?yōu)檫壿嫾,將邏輯假變(yōu)檫壿嬚妗_@樣,如果這個連接是失敗的,mysql_connect會返回一個邏輯假,!$dbcnx將等于邏輯真,這樣我們的if語句將被執(zhí)行。相反,如果這個連接是成功的,存儲在$dbcnx 中的連接標識將等于邏輯真(在PHP中,任何非零的數字都被認為是邏輯真),所以!$dbcnx會等于邏輯假,if語句將不會被執(zhí)行。

  最后一個是exit函數,這是我們遇到的第一個沒有參數的函數。這個函數的全部作用就是導致PHP停止對本頁的閱讀。如果數據庫連接失敗這是一個很好的響應,因為絕大多數情況下,如果不能連接到數據庫,這一頁不會顯示任何有用的信息。

  和我們在第二章做過的一樣,連接被建立后下一步就是選擇工作的數據庫。我們將要在第二章中所建立的笑話數據庫中工作。這個數據庫被命名為jokes。在PHP中用來選擇數據庫的另外一個函數:

mysql_select_db("jokes", $dbcnx);


  請注意我們在這兒使用了$dbcnx變量來指出了這個函數所使用的連接標識。這個參數實際上是可省略的。當省略這個參數時,函數會自動使用最后開啟的那一個連接。這個函數成功后返回邏輯真,失敗后返回邏輯假。為了謹慎起見,我們也用了一個if語句來處理錯誤:


if (! @mysql_select_db("jokes") ) {
echo( "<P>Unable to locate the joke " .
"database at this time.</P>" );
exit();
}



  當建立了連接并選擇了數據庫之后,我們可以開始使用存儲在數據庫中的數據了。

在PHP中執(zhí)行SQL查詢

  在第二章中,我們使用一個叫mysql的程序來連接到MySQL數據庫服務器,在這個程序中,我們可以輸入SQL查詢(命令)并立即顯示查詢結果。在PHP中,有著類似的機制:mysql_query函數。

mysql_query(<query>, <connection id>);


  在這兒,<query>是一個包含將執(zhí)行的SQL命令的字符串。和mysql_select_db一樣,連接標識這個參數也是可選的。

  這個函數的返回決定于發(fā)出的查詢的類型。對于絕大多數的SQL命令來說,mysql_query返回邏輯真或邏輯假來標明執(zhí)行是否成功。請參看下面這個例子,這是用來建立我們在第二章中建立的Jokes數據表的:


$sql = "CREATE TABLE Jokes ( " .
 "ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY, " .
 "JokeText TEXT, " .
 "JokeDate DATE NOT NULL " .
 ")";
if ( mysql_query($sql) ) {
echo("<P>Jokes table successfully created!</P>");
} else {
echo("<P>Error creating Jokes table: " .
 mysql_error() . "</P>");
}



  這兒使用的mysql_error將以字符串的形式返回MySQL服務器最后發(fā)出的錯誤信息。

  對于DELETE、 INSERT以及UPDATE(用來修改存儲的數據),MySQL可以知道有多少數據行被這個查詢影響。參看下面的SQL命令,這個命令我們曾在第二章中用來設置所有包含單詞“chicken”的笑話的日期:


$sql = "UPDATE Jokes SET JokeDate='1990-04-01' " .
 "WHERE JokeText LIKE '%chicken%'";
當我們執(zhí)行這個查詢時,我們可以使用mysql_affected_rows函數來顯示這個修改所影響的數據行的數目:
if ( mysql_query($sql) ) {
echo("<P>Update affected " .
mysql_affected_rows() . " rows.</P>");
} else {
echo("<P>Error performing update: " .
 mysql_error() . "</P>");
}



  SELECT命令會有一些不同,因為它會得到許多信息,而PHP必須提供方法來處理這些信息。

處理SELECT結果集

  對于絕大多數的SQL查詢來說,mysql_query函數僅僅返回邏輯真或邏輯假。而對于SELECT查詢來說,僅僅這樣顯然是不夠的。你應該還記得SELECT查詢是用來顯示數據庫中存儲的數據的。除了指出查詢成功還是失敗之外,PHP還必須得到查詢的結果。作為一個結果,當我們執(zhí)行一個SELECT查詢的時候,mysql_query會返回一個標識“結果集”的數字,這將包含了這個查詢返回的所有行的列表。如果查詢失敗,函數仍然是返回一個邏輯假。


$result = mysql_query("SELECT JokeText FROM Jokes");
if (!$result) {
echo("<P>Error performing query: " .
 mysql_error() . "</P>");
exit();
}



  假定在執(zhí)行查詢時沒有遇到錯誤,上面的代碼會定位一個有關存儲在笑話庫中所有笑話的正文的結果集,這個定位被存儲在變量$result中。因為數據庫中的笑話的數目是沒有限制的,這個結果集可能非常龐大。

  我們之前曾經提到過while循環(huán)對于處理大量的數據來說是一個非常有用的控制語句,這是我們逐個處理結果集中數據行的代碼的基本格式:


while ( $row = mysql_fetch_array($result) ) {
// process the row...
}



  在這個while循環(huán)中的條件可能看上去與我們曾經使用過的有所不同,所以我們有必要在這里解釋它的工作機理。你可以先把這個條件看成一個獨立的語句:

$row = mysql_fetch_array($result);


  mysql_fetch_array函數以一個參數(對于這個例子來說是存儲在$result變量中)接受到一個結果集,并以一個數據的形式返回結果集中的下一行。如果你還不熟悉數組的概念,不要擔心,我們會在下面詳細討論它。如果在這個結果集中不再有其它數據行時,mysql_fetch_array返回邏輯假。

  現在,我們上面的語句定義了一個值到$row變量中,與此同時,整個語句也獲得了同樣的值。這就是我們在while循環(huán)的條件中使用這個語句的原因,因為while循環(huán)會一直執(zhí)行循環(huán)直到條件等于邏輯假,結果集有幾行,這個循環(huán)就會執(zhí)行幾次,每一次$row都會得到一個下一行的值,現在剩下的就是如何在循環(huán)中從$row變量中獲得相應的值了。

  結果集中的行被描述成一個數組。數組是一個特殊類型的變量,這個變量可以包含多個值,如果你把一個變量看成是值的容器,你可以把數組看成是有間隔的容器,在每一個間隔中可以存儲一個單獨的值。對于我們的數據行來說,這個間隔是以數據表的列名命名的。如果$row是我們結果集中的一行,那么$row["JokeText"]就是這一行中JokeText列的值。所以如果我們想要顯示我們的數據庫中所在笑話的正文,while循環(huán)應該是這樣的:


while ( $row = mysql_fetch_array($result) ) {
echo("<P>" . $row["JokeText"] . "</P>");
}



  最后,作為一個總結,這是一段完整的PHP的Web頁面的代碼,它用來連接我們的數據庫,取出數據庫中所有笑話的正文,并將其在HTML中顯示出來:


<HTML>
<HEAD>
<TITLE> Our List of Jokes </TITLE>
</HEAD>
<BODY>
<?php

// Connect to the database server
$dbcnx = @mysql_connect("localhost",
 "root", "mypasswd");
if (!$dbcnx) {
echo( "<P>Unable to connect to the " .
"database server at this time.</P>" );
exit();
}

// Select the jokes database
if (! @mysql_select_db("jokes") ) {
echo( "<P>Unable to locate the joke " .
"database at this time.</P>" );
exit();
}

?>
<P> Here are all the jokes in our database: </P>
<BLOCKQUOTE>

<?php
// Request the text of all the jokes
$result = mysql_query(
"SELECT JokeText FROM Jokes");
if (!$result) {
echo("<P>Error performing query: " .
 mysql_error() . "</P>");
exit();
}

// Display the text of each joke in a paragraph
while ( $row = mysql_fetch_array($result) ) {
echo("<P>" . $row["JokeText"] . "</P>");
}
?>
</BLOCKQUOTE>
</BODY>
</HTML>



向數據庫中插入數據

  在這一節(jié)里,我們會看到我們會如何綜合利用這些工具來讓我們站點的訪問者向數據庫中添加他們自己的笑話。如果你喜歡挑戰(zhàn),你可以試試在向下看之前想想大致上應該怎么做。在這一節(jié)里只有很少新的東西。對于我們學過的東西來說,這只是一個簡單的應用。

  如果我們想要讓訪問者能夠輸入新的笑話,我們首先需要一個表單,這兒是這個表單的代碼:


<FORM ACTION="<?php echo($PHP_SELF); ?>" METHOD=POST>
<P>Type your joke here:<BR>
<TEXTAREA NAME="joketext" ROWS=10 COLS=40 WRAP></TEXTAREA><BR>
<INPUT TYPE=SUBMIT NAME="submitjoke" VALUE="SUBMIT">
</FORM>



  正如我們上面看到的那樣,這個表單在提交時會載入同一個頁面(因為我們在表單的ACTION屬性中使用了$PHP_SELF變量),但是在再次載入時請求中包含了兩個變量,首先是$joketext,這是在text域中輸入的笑話的正文,另一個是$submitjoke,這個變量的值將始終是"SUBMIT",這用來標志笑話已被提交。

   要將已提交的笑話添加到數據庫中,我們需要用mysql_query來運行一個INSERT查詢,這個查詢中將包含已經提交的$joketext變量的值:


if ("SUBMIT" == $submitjoke) {
$sql = "INSERT INTO Jokes SET " .
 "JokeText='$joketext', " .
 "JokeDate=CURDATE()";
if (mysql_query($sql)) {
echo("<P>Your joke has been added.</P>");
} else {
echo("<P>Error adding submitted joke: " .
 mysql_error() . "</P>");
}
}



  在全部的內容中只有SQL代碼中出現了一個新的東西。在這里我們使用了一個MySQL函數CURDATE()來將新插入數據庫的笑話的JokeDate列的值置為當前日期。事實上,MySQL有很多這樣的函數,但是我們只會在使用到他們時才會介紹他們,要得到一個完整的函數的說明,你可以參看MySQL參考手冊。