一、php/mysql簡介
您應該聽說過開放源代碼軟件(oss),除非最近六到八個月來您一直住在火星上。這場運動有著巨大的沖擊力,已引起一些大公司的注意。象oralce、informix,還有多家公司都開始把他們的主力數據庫產品移植到oss的產物之一 - linux操作系統上。
如果您有足夠的技術力量,擁有一個復雜龐大的關系數據庫系統(rdbms)則是如虎添翼。但是也許您對數據庫還剛剛入門,您剛剛讀了jay的文章,決定自己也來搞一個數據驅動的網站。可是您也許會發現您缺乏必要的資源來運行asp服務器或昂貴的數據庫系統(您也不需要這些東西)。您需要一些免費的、支持unix的東西。
那么我建議您使用php和mysql。這兩樣東西加在一起,對于開發數據驅動的網站這項工作而言,真是最佳組合。其實用不著我多費唇舌解釋。一項由netcraft組織的非官方調查顯示,應用php的主機數目由1998年6月的7,500臺躍升至1999年3月的410,000臺。不錯吧?這兩種軟件的組合還在webcon98大會上贏得了年度數據庫產品大獎,還得了一座漂亮的獎杯。
mysql是一個小巧靈瓏的數據庫服務器軟件,對于小型(當然也不一定很小)應用系統是非常理想的。除了支持標準的ansi sql語句,它還支持多種平臺,而在unix系統上該軟件支持多線程運行方式,從而能獲得相當好的性能。對于不使用unix的用戶,它可以在windows nt系統上以系統服務方式運行,或者在windows 95/98系統上以普通進程方式運行。
php是一種服務器端解釋的腳本語言。如果你接觸過asp的話,那么您對于在html頁面中嵌入代碼應該是比較熟悉了。php代碼在服務器一端被解釋轉變成普通的html頁面內容,送給瀏覽器一端。這種模式使得我們可以用它來完成相當復雜的功能。
除了免費這一點(當然,mysql也有一些使用許可方面的限制),php-mysql的組合還可以跨平臺運行,這意味著您可以在windows上開發,然后在unix平臺上運行。另外,php也能作為標準的cgi進程來運行,此時它是一個獨立的腳本解釋器,或者是apache的一個嵌入模塊。
如果您有興趣使用其他數據庫服務器的話,php也支持informix、oracle、sybase、solid和postgresql ,以及通用的odbc。
php支持internet開發的一些前沿技術。這些技術包括身份認證、xml、動態圖象生成、wddx、共享內存,以及動態pdf文檔等等,不一而足。如果您還不滿意的話,php是很容易擴展的,所以只要您有編程能力,您盡可以自己大展身手一番。
最后要說的是,兩種軟件都是大量程序員協同開發的,因此文檔及郵件列表等支持方式很多。程序錯誤的修正很快,而如果您要求加入新功能的話,總會有人考慮您的要求,并且在可行性足夠高的前提下加以實現。
說得夠多了!我們來看看這篇教程里都有些什么內容吧。
第一課講的是在unix和windows環境下安裝這兩個軟件。如果您不太關心這個問題(也許您是在isp的服務器上開發),您可以直接跳到第一個示例程序,從那里開始您的奇妙之旅。
在第二課里,我們要學習一些更加復雜的腳本功能,比如循環、處理用戶輸入,以及與數據庫交換數據等等。
第三課要講的是確認功能,以及如何使您的腳本程序清晰簡練。
我們開始吧。>>
二、安裝mysql
快點行動,拿到這些軟件包,仔細研究一下吧。這可不是件容易的事兒。你從獲取軟件包、編譯軟件包到安裝軟件包的過程中都有不少的選擇項。我們先從mysql開始,因為有了它才能運行php。
mysql中央網站是http://www.mysql.com/。為了方便人們下載使用(這軟件還是比較大的),全球有許許多多的鏡像網站。為更有效地利用因特網,請找一個就近的網站下載。
在這時候你也會有多種選擇。如果你是發燒友的話,可以下載源代碼;否則,網上也有各種平臺上運行的預先編譯過的二進制文件可以直接下載。
另外,mysql還為windows用戶準備了一個共享軟件版本,它的版本號稍低一些。如果你想要最新的版本,得花錢買一個軟件許可。mysql還提供了odbc驅動程序,使前端應用程序可以訪問mysql數據庫。有關其他一些詳細信息在它的網站上都有得介紹,您可以去看看。
預先編譯過的unix版本和windows版本都很簡單,只須解包即可使用,不需要做太多說明了。因此,我們來介紹一下源代碼的編譯。windows用戶請記住,您需要運行mysqld程序,該程序是在mysql/bin目錄下。
下載壓縮過的軟件包文件,放在一個目錄下。使用gzip和tar來解壓縮和解包。比較快的做法是使用下面這樣的命令:
gunzip < mysql-xxxx.tar.gz | tar xvf -
其中,xxxx是你自己任取的一個版本標記。上面的命令將創建一個名為mysql-xxxx目錄,所有的源程序文件都在這個目錄下。通過執行cd mysql-xxxx命令轉入該目錄,仔細閱讀其中的多個readme文件install文件。在遇到某些問題時,這些文件可能會幫上大忙呢。
mysql帶有一些便利的配置腳本程序。只須簡單地鍵入./configure,您就可以讓這些程序為您完成很多工作。如果您需要明確指定要做的事情,可以使用./configure -help命令,它會給您列出你可以使用的選項。例如,如果您正在一臺內存較少的機器上進行編譯,那么可以使用--with-low-memory選項。我喜歡把mysql安裝在一個總目錄下,而不是安裝在機器上多個目錄下,所以我會指定安裝目錄,并指定-prefix選項。
您還可以指定許多其他選項,象編譯過程中要略掉哪些部分、保留哪些部分等。我們不妨假定要全部安裝在服務器的/usr/local/mysql目錄下。這意味著我們將鍵入./configure -prefix=/usr/local/mysql命令。
配置腳本程序運行時會檢查您的系統,然后生成一些文件來保證編譯的順利進行。如果該腳本程序失敗,它也會顯示一些有用的錯誤信息告訴您失敗的原因。大家經常會遇到腳本程序在尋找多線程庫文件時失敗。此時您應當檢查一下系統中是否已經安裝了mit-pthreads,如果沒有,那么請您安裝該軟件。linux用戶則必須安裝linuxthreads。這些庫文件對于mysql的多線程運行模式(也就是運行它自己的多個版本〕是非常關鍵的。
如果一切都順利進行的話,只須簡單鍵入make命令,然后就可以去泡杯咖啡了。mysql是相當復雜的程序,編譯起來得用一段時間。如果發現錯誤,可以檢查文檔,看看只否您漏掉了某些與您的操作系統有關的準備工作。
接下來,鍵入make install命令,所有必需的文件都會安裝到相應的目錄。您差不多就可以開始使用了!如果您是mysql新手,以前從未安裝過mysql,那您得創建默認的許可權限才能安裝,因此請鍵入...scripts/mysql_install_db來進行相應的設置。
就這樣。我們的準備工作完成了。再下面所要做的就是在機器啟動時自動啟動數據庫,并在關機時自動關閉數據庫。是的,這項工作也有一個專門的腳本程序。mysql.server start命令可以啟動數據庫,而mysql.server stop可以關閉數據庫。實在是再簡單不過了。如果您想手動啟動數據庫(這樣就不用重啟機器了),你以進到安裝mysql的最上層目錄(/usr/local/mysql)然后鍵入bin/safe_mysqld &命令。
我們已經完成了一半了。接下來是php部分。>>
三、安裝php
好,看到這里時,希望您已經把mysql安裝好并運行起來了。那實在是太有意思了!下面是php...這個過程要容易一些,不過那些大量的選項還是使人眼花繚亂。當然,您大可不必驚慌。您隨時可以重頭再來,重新編譯php,根據需要來加入或去掉某個選項。
php的老家在http://www.php.net/。這個網站信息量極大,從開發項目內容到軟件錯誤報告都有。和mysql一樣,您可以選一個離您最近的鏡像網站下載。很顯然,您得到網站的downloads部分去下載php。
這里您的選擇不是很多。有一些預選編譯好的二進制文件,但那都是實驗性的。如果您不是在windows平臺上,那就下載源代碼,自己編譯一下吧。
但是我們還是先談談windows。在使用php時,一般的作法是在windows系統上開發,然后在unix服務器上運行。您最終可能也會選擇這種方式,這就需要您對兩種平臺下的安裝都很熟悉才行。
下載windows二進制文件后,您可以用您喜歡的任何一種zip解壓縮程序,把軟件包中的文件解壓到c盤的php3目錄下。軟件包中的readme文件對安裝過程中的細節作了部分說明,但是我們在這里再對這個文件中的關鍵內容做個讀者文摘:如果您不想把php安裝在c:/php3目錄,而是別的目錄,那么您得編輯解壓縮出來的文件中那個.inf文件。
在php3目錄中,您會發現很多.dll文件。把所有文件名不是以php_開頭的那些.dll文件都移到/windows/system目錄下。然后,把php.ini-dist文件改一下名,改成php3.ini,并把它移到/windows目錄下。如果您打開這個文件,會發現里面有很多有趣的東西可以改。現在,把含有:
extension=php3_mysql.dll
內容的那一行的注釋去掉。
如果您使用的是win32平臺上的apache服務器,那么請設置apache,使其能夠識別并解釋php文件。您需要在http.conf文件或是srm.conf文件(具體是哪一個文件取決于您使用的apache軟件的版本)中加入下一行:
action application/x-httpd-php3 "php3/php.exe"
addtype application/x-httpd-php3 .php3
或者,如果您使用的是iis,那么請用鼠標右鍵單擊php_iis_reg.inf文件,并選擇“安裝”。您得重新啟動系統,才能使剛才所做的改動生效。
ok,說完了windows,再來說說unix。當然,我們要從源代碼開始編譯。與mysql相似,把源文件下載、解包。php也同樣包含一個配置腳本程序,可是您不能完全使用默認設置。運行./configure -help | more命令,可以逐頁地觀看有哪些新的、有趣的選項。您必須選擇是把php編譯成外部cgi程序還是apache內嵌模塊。如果您正在使用apache web服務器,并且您可以對它進行重新編譯的話,請選擇內嵌模塊方式,這種方式運行更快,使用也更簡便。否則,您可以選cgi方式。另外,您還得指定將對mysql的支持部分編譯進去。
現在我們假定要以內嵌模塊方式編譯,并帶有mysql支持部分。如果隨后您需要增加其他選項或庫文件的話,可以在以后再加進去。鍵入下面的命令:
./configure -with-apache=/path/to/apache/dir -with-mysql=/usr/local/mysql
如果您打算以外部cgi程序方式來編譯的話,請去掉-with-apache選項。配置程序運行起來后,會創建相應的系統文件。接下來簡單地執行make命令就行了。
又可以喝一杯咖啡了。如果您在此時感到坐立不安的話,不必擔心。每個人在初次安裝php的時候都有一點近不及待的感覺。再多喝點咖啡就是了。
如果您選擇cgi程序方式來編譯,那么現在可以就可以使用了。只須把產生的可執行文件復制到cgi程序目錄下就行了。如果您使用apache內嵌模塊方式來編譯,要再執行一下make install命令,把有關文件復制到apache目錄下。在該目錄下,您可以按照apache的文檔說明,向其中加入php模塊,并重新編譯apache。
現在您得告訴web服務器如何通過php程序來處理頁面內容。如果您使用的不是apache,那您需要查閱web服務器軟件的文檔,看看如何讓它處理后綴是.php3的文件。apache 1.3.x版本的用戶僅須在httpd.conf或srm.conf文件中加入:addtype application/x-httpd-php3 .php3。如果您使用的是cgi程序方式,那您在addtype前面還得加入下面內容:
action application/x-httpd-php3 "php3/php.exe
就是這樣。您的運氣還不那么差,現在mysql也運行起來了,php也工作正常了。別忘了,在遇到問題時可以去查閱常見問題解答和軟件文檔。還可以試試電子郵件討論組。
既然我們已經進行了這么多,下面我們可以實際操練了。>>
四、第一個腳本
如果我告訴您真正難過的一關已經過了,您一定會很高興。軟件的安裝過程總是無法預料,因為系統跟系統之間可以說是千差萬別。不過您運氣不錯,數據庫運行起來,php也編譯安裝完畢,web服務器也可以正確處理擴展名為.php3的文件了。
我們下面就開始正式上路,要寫第一個腳本程序了。創建一個文本文件,在其中加入下面的內容:
<html><body><?php$myvar = "hello world";echo $myvar;?></body></html>
現在,訪問相應的url,例如,http://myserver/test.php3。您應該可以看到頁面中包含“hello world”的文字。如果您看到的是錯誤信息,查一下php文檔,看看軟件設置是否正確無誤。
就是這樣了!這是您的第一個php程序。如果您查看一下這個頁面的html源代碼,您會發現里面只有hello world 這樣的文字。
那是因為php引擎過濾了文件內容,對其中的代碼作了處理,轉換成了標準的html。
在上面的程序中您最先注意到的可能是定界符,也就是以<?php開始的那幾行。這個標記說明后面是php代碼,而?>表示代碼結束。php的強大之處在于,這些代碼可以以多種不同方式放在任意位置 - 我是說任意位置。后面我們會看到一些很有趣的例子,現在我們還是從最簡單的開始。如果您愿意,也可以設置php,讓它使用短標記,<?和?>,但這與xml會發生沖突,所以要小心使用。如果您是從asp轉向php,您甚至可以讓php使用<%和%>作為定界符。
您還會注意到每行后面的分號。這些分號稱為分隔符,用于分隔不同的指令。您可以把所有的php代碼寫在一行里,用分隔符把命令分開。但是那樣看起來很亂,所以我們在每個分號后面都另起一行。記住,每行最后都要以分號結束。
最后,您會注意到myvar這個字以$符號開頭。這個符號告訴php,這是一個變量。我們把“hello world”賦給變量$myvar。一個變量可以是數字,也可以是數組。不管怎樣,所有的變量都是以$符開頭。
php真正強大之處來源于它的函數。函數,基本上是處理指令序列。如果您把所有的選件都編譯進php,總共會有超過700個函數。這些函數可以讓您做很多事情。
現在我們再加進一些mysql的內容進去。>>
五、裝載數據庫
現在,我們要加入mysql的內容了。要想知道php中包含哪些選項,或服務器方面的一些情況,一種簡便的方法是使用函數phpinfo()。創建一個象下面這樣的程序:
<html><body><?phpphpinfo();?></body></html>
保存這個程序,在瀏覽器中訪問這個文件。您會看到網頁中包含了一些有趣的、有用的信息,象這樣。這些信息是有關服務器、web服務器內部環境變量、php中包含的選項,等等。在第一段extensions中,找到以mysql開頭的一行。如果沒有找到,那說明mysql支持選項并沒有編譯進php。您可以再檢查一下安裝步驟,查閱一下php文檔,看您是否漏掉了什么。
如果找到了mysql那一行,那您可以繼續了。
從mysql數據庫中讀取數據之前,我們得先往數據庫里放一些數據。在現在這一階段,還沒有一個簡便的方法來做這件事情。大多數的php程序都帶有一個數據文件,該文件包含一些數據來創建并激活mysql數據庫。這個過程不在本教程范圍之內,所以讓我來替您做這件事情吧。
mysql使用它自己的用戶權限表。在安裝時,會創建一個默認的用戶(root),該用戶是沒有口令的。數據庫管理員可以根據需要來增加用戶并賦予用戶各種不同的權限,但這項工作完全可以另寫一本書了,所以我們只使用root用戶。如果您自己管理服務器和數據庫,為root用戶分配一個口令是很重要的。
總之,我們還是接著說數據庫吧。對win32用戶來說,很對不起,不過您要在dos下做些工作。您不得不使用dos窗口,或者在“執行”窗口中鍵入所有命令。別忘了,輸入命令時要帶上mysql/bin的目錄名。unix用戶可以在mysql的bin目錄下輸入命令,但命令必須以./開頭,才能讓程序運行起來。
我們要做的第一件事情是實際創建出數據庫。在命令行下,鍵入下列命令:
mysqladmin -u root create mydb
這樣就創建了一個名為“mydb”的數據庫。-u選項告訴mysql我們使用的是root用戶。
下一步,我們要加入一些數據,這里我們用的示例數據是大家都喜歡用的員工數據庫。我們將會用到我前面提到過的數據文件。如果您想在這方面多了解一些,可以查閱mysql所帶的手冊或訪問 http://www.turbolift.com/mysql/網站。
把下面的文字復制到一個文件中,把該文件存在mysql的bin目錄下(我假定文件名是mydb.dump)。
create table employees ( id tinyint(4) default '0' not null auto_increment, first varchar(20), last varchar(20), address varchar(255), position varchar(50), primary key (id), unique id (id));insert into employees values (1,'bob','smith','128 here st, cityname','marketing manager');insert into employees values (2,'john','roberts','45 there st , townville','telephonist');insert into employees values (3,'brad','johnson','1/34 nowhere blvd, snowston','doorman');
如果文字是折行的,請確保每一個insert語句都是另起一行的。現在,我們要把數據加入到mydb數據庫中了。在命令行下,鍵入下面的命令:
mysql -u root mydb < mydb.dump
此時您應該不會遇到什么錯誤。如果真的出錯了,請仔細檢查一下是否因上面的文字折行而引起錯誤。>>
六、測試
ok,現在我們已經把數據導入到數據庫中了。現在我們來處理這些數據。把下面的文字存入一個文件中,把該文件存在web服務器的文檔目錄下,后綴名為.php3。
<html><body><?php$db = mysql_connect("localhost", "root");mysql_select_db("mydb",$db);$result = mysql_query("select * from employees",$db);printf("first name: %s<br>/n", mysql_result($result,0,"first"));printf("last name: %s<br>/n", mysql_result($result,0,"last"));printf("address: %s<br>/n", mysql_result($result,0,"address"));printf("position: %s<br>/n", mysql_result($result,0,"position"));?></body></html>
我來解釋一下上面的代碼。mysql_connect()函數負責以指定的用戶名(本例中用戶名是root)連接到指定機器(在本例中機器是本機localhost)上的mysql數據庫。如果您想指定用戶口令,您也可以把它送給這個函數。連接的結果保存在變量$db中。
隨后,mysql_select_db()函數告訴php,我們要讀取的數據庫是mydb。我們可以在程序中同時連接到多臺機器上的多個數據庫,但目前我們還是限于連接一個數據庫。
接下來,mysql_query()函數完成最復雜的部分。利用剛才得到的連接結果標識,該函數把一行sql語句送給mysql服務器去處理。返回的結果保存在變量$result中。
最后,mysql_result()函數顯示sql查詢命令所得到的各個字段的值。利用變量$result,我們就可以找到第一條記錄,記錄號是0,并將其中各字段的值顯示出來。
如果您以前沒用過perl或c語言,那么printf函數的語法格式會顯得很奇怪。在上面的每一行程序中,%s代表表達式第二部分中的那個變量(例如,mysql_result($result,0,"position"))應該以字符串的形式顯示出來。想更深入了解printf,請參閱php文檔。
這一課我們就講到這里了。我們已經成功地編譯、安裝和設置了mysql和php,并且運行了一個簡單的程序來讀取數據庫中的信息。在 第二課里,我們會做一些更復雜的工作,來顯示多行記錄的數據,甚至與數據庫互相交換數據。
繼續努力吧!
一、 while循環
在這一課里,我們將會繼續深入下去,使用php和mysql來寫出一些簡單而有用的頁面。我們從昨天創建的數據庫開始,顯示庫中的數據,但是會再稍微加以潤色。
首先,我們用下面的代碼來查詢數據庫內容。
<html><body><?php$db = mysql_connect("localhost", "root");mysql_select_db("mydb",$db);$result = mysql_query("select * from employees",$db);echo "<table border=1>/n";echo "<tr><td>姓名</td><td>職位</td></tr>/n";while ($myrow = mysql_fetch_row($result)) {printf("<tr><td>%s %s</td><td>%s</td></tr>/n", $myrow[1], $myrow[2], $myrow[3]);}echo "</table>/n";?></body></html>
您可能已經注意到,我們在這個程序里加進了一些新東西。最明顯的是while()循環。該循環是說,只要數據庫里還有記錄可讀(使用mysql_fetch_row()函數),那就把該記錄賦給變量$myrow,然后執行大括號({})內的指令。仔細看一下這里,這部分是比較重要的。
我們應該注意一下mysql_fetch_row()函數。這里有一點小問題,它返回的是一個數組,必須以數組下標來訪問其中的某個字段。第一個字段下標為0,第二個是1,依此類推。在執行某些復雜查詢時,這么做簡直實在是太煩瑣了。
現在我們更仔細地研究一下循環過程。程序前幾行我們在第一課的例子中已經看到過了。然后,在while()循環中,我們從查詢結果中讀取一條記錄并把該記錄賦給數組$myrow。接著,我們用printf函數把數據中的內容顯示在屏幕上。隨后,循環反復執行,讀取下一條記錄賦給$myrow。這樣繼續下去,直到所有記錄都已被讀取完為止。
使用while()循環的一個好處是,如果數據庫查詢沒有返回任何記錄,那您也不會收到錯誤信息。在剛執行循環語句時,循環條件就不滿足,不會有任何數據賦給$myrow,程序就直接往下運行了。
但是如果查詢未返回任何數據,我們怎么讓用戶知道這一點呢?我們也許該提供點兒相關的消息給用戶吧。這是可以做到的,下面我們就看看怎么做。>>
二、 if-else
請看下面的程序。
<html><body><?php$db = mysql_connect("localhost", "root");mysql_select_db("mydb",$db);$result = mysql_query("select * from employees",$db);if ($myrow = mysql_fetch_array($result)) { echo "<table border=1>/n"; echo "<tr><td>姓名</td><td>住址</td></tr>/n"; do { printf("<tr><td>%s %s</td><td>%s</tr>/n", $myrow["first"], $myrow["last"], $myrow["address"]); } while ($myrow = mysql_fetch_array($result));echo "</table>/n";} else {echo "對不起,沒有找到記錄!"; }?></body></html>
這段程序中包含有不少新內容,不過這些內容都相當簡單。首先是mysql_fetch_array()函數。該函數與mysql_fetch_row()十分相近,只有一點不同:使用這個函數時,我們可以通過字段名而不是數組下標來訪問它返回的字段,比如$myrow["first"]。這樣我們就可以省不少力氣了。另外,程序中還加進了do/while循環和if-else條件判定語句。
if-else條件判定語句的含意是,如果我們成功地把一條記錄賦給了$myrow變量,那就繼續;否則,就跳到else部分,執行那里的指令。
do/while循環是我們在上頁中用戶的while()循環的一個變體。我們要用到do/while的原因是:在最初的if語句中,我們已經把查詢返回的第一條記錄賦給變量$myrow了。如果這時我們執行一般的while循環(比如,while ($myrow = mysql_fetch_row($result)),那我們就會把第二條記錄賦給$myrow,而第一條記錄就被沖掉了。但是do/while循環可以讓我們執行一次循環體內容之后再來判定循環條件。因此,我們就不會不小心漏掉第一條記錄了。
最后,如果查詢結果沒有任何記錄的話,程序就會執行包含在else{}部分的那些語句。如果您想看到這部分程序的執行情況,可以把sql語句改為select * from employees where id=6,或改成其他形式,使得查詢結果中沒有任何記錄。
下面我們來擴充一下循環if-else 代碼,使得頁面內容更加豐富。相信您會喜歡的。>>
三、 第一個程序腳本
我們剛剛學到了循環語句,下面我們將在一個更加實際一點的例子中看看如何運用它。但是在這之前,您應該知道如何處理web表格、查詢參數串,以及表單的get方法和post方法。不久之前我們剛剛有文章介紹這部分內容,您如果對這一部分還不太熟悉的話可以看看那篇文章。
現在,我們要處理查詢參數串,正如您所知道的,有三種方法可以把參數內容寫入到查詢參數串中。第一種是在表格中使用get方法;第二種是在瀏覽器的地址欄中輸入網址時直接加上查詢參數;第三種是把查詢參數串嵌入到網頁的超鏈接中,使得超鏈接的內容象下面這樣:<a href="http://my_machine/mypage.php3?id=1">。我們現在要用到最后這一種方法。
一開始,我們再來查詢我們的數據庫,列出員工姓名。看看下面的程序,其中大部分內容我們都已經很熟悉了。
<html><body><?php$db = mysql_connect("localhost", "root");mysql_select_db("mydb",$db);$result = mysql_query("select * from employees",$db);if ($myrow = mysql_fetch_array($result)) { do { printf("<a href=/"%s?id=%s/">%s %s</a><br>/n", $path_info, $myrow["id"], $myrow["first"], $myrow["last"]); } while ($myrow = mysql_fetch_array($result));} else { echo "對不起,沒有找到記錄!"; }?></body></html>
這里沒什么特別的,只是printf函數有些不同。那我們就來仔細研究一下。
首先要注意的是,所有的引號前面都有一個反斜杠。這個反斜杠告訴php直接顯示后面的字符,而不能把后面的字符當作程序代碼來處理。另外要注意變量$path_info的用法。該變量在所用程序中都可以訪問,是用來保存程序自身的名稱與目錄位置的。我們之所以用到它是因為要在頁面中再調用這個程序本身。使用$path_info,我們可以做到,即使程序被挪到其他目錄,甚至是其他機器上時,我們也能保證正確地調用到這個程序。
正如我剛才提到的,程序所生成的網頁,其中包含的超鏈接會再次調用程序本身。不過,再次調用時,會加入一些查詢參數。
php見到查詢參數串中包含有“名字=值”這樣的成對格式時,會作一些特別的處理。它會自動生成一個變量,變量名稱與取值都與查詢參數串中所給定的名稱和取值相同。這一功能使得我們可以在程序中判斷出是第一次執行本程序還是第二次。我們所要做的只是問問php$id這個變量是否存在。
當我知道這個問題的答案后,我可以在第二次調用程序時顯示一些不同的結果出來。請看:
<html><body><?php$db = mysql_connect("localhost", "root");mysql_select_db("mydb",$db);// display individual record// 顯示單條記錄內容if ($id) { $result = mysql_query("select * from employees where id=$id",$db); $myrow = mysql_fetch_array($result); printf("名: %s/n<br>", $myrow["first"]); printf("姓: %s/n<br>", $myrow["last"]); printf("住址: %s/n<br>", $myrow["address"]); printf("職位: %s/n<br>", $myrow["position"]);} else { // show employee list // 顯示員工列表 $result = mysql_query("select * from employees",$db); if ($myrow = mysql_fetch_array($result)) { // display list if there are records to display // 如果有記錄,則顯示列表 do { printf("<a href=/"%s?id=%s/">%s %s</a><br>/n", $path_info, $myrow["id"], $myrow["first"], $myrow["last"]); } while ($myrow = mysql_fetch_array($result)); } else { // no records to display // 沒有記錄可顯示 echo "對不起,沒有找到記錄!"; }}?></body></html>
程序開始變得復雜了,所以我在這里面加了注釋,來解釋一下到底發生了什么。您可以用//加入單行注釋,或者用/*和*/來括住大段的注釋。
到這里,我們已經學會了第一個真正有用的php/mysql腳本程序!現在,我們要看看怎樣把web表格加進來,并且向數據庫發送數據。>>
四、 向服務器發送數據
現在我們從數據庫讀取數據已經沒有太多困難了。但是怎么反過來向數據庫發送數據呢?其實這不是php的問題。
首選,我們創建一個帶有簡單表格的網頁。
<html><body><form method="post" action="<?php echo $path_info?>">名:<input type="text" name="first"><br>姓:<input type="text" name="last"><br>住址:<input type="text" name="address"><br>職位:<input type="text" name="position"><br><input type="submit" name="submit" value="輸入信息"></form></body></html>
同樣要注意$path_info的用法。就象我在第一課里講到的,您可以在html代碼中的任意位置使用php。您也會注意到,表格中的每一個元素都對應著數據庫中的一個字段。這種對應關系并不是必須的,這么做只是更直觀一些,便于您以后理解這些代碼。
還要注意的是,我在submit按鈕中加入了name屬性。這樣我在程序中可以試探$submit變量是否存在。于是,當網頁被再次調用時,我就會知道調用頁面時是否已經填寫了表格。
我應該指出,您不一定要把上面的網頁內容寫到php程序中,再返過來調用程序本身。您完全可以把顯示表格的網頁和處理表格的程序分開放在兩個網頁、三個網頁甚至更多網頁中,悉聽尊便。放在一個文件中只是可以使內容更加緊湊而已。
那好,我們現在加入一些代碼,來檢查用戶在表格中輸入的內容。我會把用$http_post_vars把所有查詢參數變量都顯示出來,這只不過是為了證明php確實把所有變量都傳給了程序。這種方法是一個很有用的調試手段。如果您要想看全部的變量,可以用$globals。
<html><body><?phpif ($submit) { // 處理表格輸入 while (list($name, $value) = each($http_post_vars)) { echo "$name = $value<br>/n"; }} else{ // 顯示表格 ?> <form method="post" action="<?php echo $path_info?>"> 名:<input type="text" name="first"><br> 姓:<input type="text" name="last"><br> 住址:<input type="text" name="address"><br> 職位:<input type="text" name="position"><br> <input type="submit" name="submit" value="輸入信息"> </form> <?php} // end if,if結束?></body></html>
程序現在運行正常,那我們現在就可以取到表格輸入的內容,并把它們發送給數據庫。
<html><body><?phpif ($submit) { // 處理表格輸入 $db = mysql_connect("localhost", "root"); mysql_select_db("mydb",$db); $sql = "insert into employees (first,last,address,position) values ('$first','$last','$address','$position')"; $result = mysql_query($sql); echo "thank you! information entered./n";} else{ // 顯示表格內容 ?> <form method="post" action="<?php echo $path_info?>"> 名:<input type="text" name="first"><br> 姓:<input type="text" name="last"><br> 住址:<input type="text" name="address"><br> 職位:<input type="text" name="position"><br> <input type="submit" name="submit" value="輸入信息"> </form> <?php} // end if,if結束?></body></html>
您現在已經向數據庫中插入數據了。不過還有很多完善的工作要做。如果用戶沒有填寫某一欄怎么辦?在需要填入數字的地方填了文字怎么辦?或者填錯了怎么辦?
別擔心。我們一步一步來。>>
五、修改數據
在個教程中,我都把要執行的sql語句放到一個變量($sql)中,然后才用mysql_query()來執行數據庫查詢。在調試時這是很有用的。如果程序出了什么問題,您隨時可以把sql語句的內容顯示出來,檢查其中的語法錯誤。
我們已經學習了如何把數據插入到數據庫中。現在我們來學習如何修改數據庫中已有的記錄。數據的編輯包括兩部分:數據顯示和通過表格輸入把數據返回給數據庫,這兩部分我們前面都已經講到了。然而,數據編輯還是有一點點不同,我們必須先在表格中顯示出相關的數據。
首先,我們回過頭再看看第一課的程序代碼,在網頁中顯示員工姓名。但是這次,我們要把數據顯示在表格中。程序看起來象下面這樣:
<html><body><?php$db = mysql_connect("localhost", "root");mysql_select_db("mydb",$db);if ($id) { // 查詢數據庫 $sql = "select * from employees where id=$id"; $result = mysql_query($sql); $myrow = mysql_fetch_array($result); ?> <form method="post" action="<?php echo $path_info?>"> <input type=hidden name="id" value="<?php echo $myrow["id"] ?>"> 名:<input type="text" name="first" value="<?php echo $myrow["first"] ?>"><br> 姓:<input type="text" name="last" value="<?php echo $myrow["last"] ?>"><br> 住址:<input type="text" name="address" value="<?php echo $myrow["address"] ?>"><br> 職位:<input type="text" name="position" value="<?php echo $myrow["position"] ?>"><br> <input type="submit" name="submit" value="輸入信息"> </form> <?php} else { // 顯示員工列表 $result = mysql_query("select * from employees",$db); while ($myrow = mysql_fetch_array($result)) { printf("<a href=/"%s?id=%s/">%s %s</a><br>/n", $path_info, $myrow["id"], $myrow["first"], $myrow["last"]); }}?></body></html>
我們剛才是把字段內容寫入到相應表格元素中的value屬性里,這是相應簡單的。我們再往前進一步,使程序可以把用戶修改過的內容寫回數據庫去。同樣,我們通過submit按鈕來判斷是否處理表格輸入內容。還要注意,我們用的sql語句稍稍有些不同。
<html><body><?php$db = mysql_connect("localhost", "root");mysql_select_db("mydb",$db);if ($id) { if ($submit) { $sql = "update employees set first='$first',last='$last', address='$address',position='$position' where id=$id"; $result = mysql_query($sql); echo "謝謝!數據更改完成/n"; } else { // 查詢數據庫 $sql = "select * from employees where id=$id"; $result = mysql_query($sql); $myrow = mysql_fetch_array($result); ?> <form method="post" action="<?php echo $path_info?>"> <input type=hidden name="id" value="<?php echo $myrow["id"] ?>">名:<input type="text" name="first" value="<?php echo $myrow["first"] ?>"><br> 姓:<input type="text" name="last" value="<?php echo $myrow["last"] ?>"><br> 住址:<input type="text" name="address" value="<?php echo $myrow["address"] ?>"><br> 職位:<input type="text" name="position" value="<?php echo $myrow["position"] ?>"><br> <input type="submit" name="submit" value="輸入信息"> </form><?php}} else { // 顯示員工列表 $result = mysql_query("select * from employees",$db); while ($myrow = mysql_fetch_array($result)) { printf("<a href=/"%s?id=%s/">%s %s</a><br>/n", $path_info, $myrow["id"], $myrow["first"], $myrow["last"]); }}?></body></html>
就是這樣。在這個程序中已經包含了我們學過所大多數特性。您也已經看到,我們在一個if()條件判別語句中又加了一個if()語句,來檢查多重條件。
下面,我們要把所有東西全都加在一起,寫出一個很好的程序來。>>
六、完整的程序
在本課結束前,我們要把所有東西加入到一個程序中,使它具有增加、編輯修改、刪除記錄的功能。這是前面所有內容的一個延伸,也可以作為極好的復習方法。看看下面的程序。
<html><body><?php$db = mysql_connect("localhost", "root");mysql_select_db("mydb",$db);if ($submit) { // 如果沒有id,則我們是在增加記錄,否則我們是在修改記錄 if ($id) { $sql = "update employees set first='$first',last='$last', address='$address',position='$position' where id=$id"; } else { $sql = "insert into employees (first,last,address,position) values ('$first','$last','$address','$position')"; } // 向數據庫發出sql命令 $result = mysql_query($sql); echo "記錄修改成功!<p>";} elseif ($delete) {// 刪除一條記錄 $sql = "delete from employees where id=$id"; $result = mysql_query($sql); echo "記錄刪除成功!<p>";} else { // 如果我們還沒有按submit按鈕,那么執行下面這部分程序 if (!$id) { // 如果不是修改狀態,則顯示員工列表 $result = mysql_query("select * from employees",$db); while ($myrow = mysql_fetch_array($result)) { printf("<a href=/"%s?id=%s/">%s %s</a> /n", $path_info, $myrow["id"], $myrow["first"], $myrow["last"]); printf("<a href=/"%s?id=%s&delete=yes/">(delete)</a>< br>", $path_info, $myrow["id"]); } } ?> <p> <a href="<?php echo $path_info?>">add a record</a> <p> <form method="post" action="<?php echo $path_info?>"> <?php if ($id) { // 我們是在編輯修改狀態,因些選擇一條記錄 $sql = "select * from employees where id=$id"; $result = mysql_query($sql); $myrow = mysql_fetch_array($result); $id = $myrow["id"]; $first = $myrow["first"]; $last = $myrow["last"]; $address = $myrow["address"]; $position = $myrow["position"]; // 顯示id,供用戶編輯修改 ?> <input type=hidden name="id" value="<?php echo $id ?>"> <?php } ?> 名:<input type="text" name="first" value="<?php echo $first ?>"><br> 姓:<input type="text" name="last" value="<?php echo $last ?>"><br> 住址:<input type="text" name="address" value="<?php echo $address ?>"><br> 職位:<input type="text" name="position" value="<?php echo $position ?>"><br> <input type="submit" name="submit" value="輸入信息"> </form><?php}?></body><`/html>
這段程序看起來很復雜,但實際上并不難。程序主要有三個部分。第一個if()語句檢查我們是否已經按下了那個“輸入信息”的數據提交按鈕。如果是,程序再檢查$id是否存在。如果不存在,那我們就是在增加記錄狀態,否則,我們是在修改記錄狀態。
接下來我們檢查變量$delete是否存在。如果存在,我們是要刪除記錄。注意,第一個if()語句檢查的是用post方法發送來的變量,而這一次我們檢查的是get方法中傳遞過來的變量。
最后,程序默認的動作是顯示員工列表和表格。同樣,我們要檢查變量$id是否存在。如果存在,我們就根據它的值檢索出相應的記錄顯示出來。否則,我們會顯示一個空的表格。
現在,我們已經把所學的東西全部都放在一個程序里頭了。我們用到了while()循環,用到了if()語句,并且執行了全部的sql基本操作 - select、insert、update以及delete。另外,我們也知道如何在不同的網頁之間通過url和表格輸入來互相傳遞信息。
在第三課里,我們要學習如何為網頁增加智能化處理能力。
一、基本函數
歡迎來到本教程的第三課,也是最后一課。如果您已經學過第一課和第二課,那么您已經掌握了mysql和php的安裝及編程的基本知識。下面我們要介紹php的一些其他函數,這些函數可能會對您有用,使您的開發過程更加簡單。首先我們來看看頭文件。
大家應該知道頭文件的一些基本概念吧?頭文件是一個外部文件,它的內容被包含到主程序中。方法也十分簡單:在程序文件中引用頭文件名,這個頭文件就會包含進來了。在php中使用頭文件,會涉及兩個函數:include()和require()。這兩個函數差別很小,卻很重要,所以我們要認真研究一下。require()函數工作方式與xssi相類似;不管在程序的哪個部分使用了這個函數,只有程序一開始運行,頭文件的內容就被作為程序本身的一部分來處理。因此,如果您在一個條件判定語句中使用了require()函數,那么即使這個條件即使不為真,頭文件也會被包含進來。
而include()函數只是在執行到這一條語句時才會把頭文件內容包含進來。如果程序沒運行到這里,那php是不會管它的。這就意味著,您在條件判定部分使用include時,它會完全按照您希望的那樣工作。
還有,如果您用了require()函數,而您指定的頭文件并不存在,那么程序將會停止運行并產生錯誤。如果您用了include(),程序會產生一個警告信息,但是會繼續運行。您可以親自試一下,運行下面的程序,然后把include()換成require(),再比較兩個程序運行的結果。
<html><body><?phpinclude("emptyfile.inc");echo "hello world";?></body></html>
我喜歡把頭文件的后綴名起成.inc,這樣就可以把頭文件和一般的程序區分開來。如果您也這么做,那么請您修改web服務器軟件的配置文件,使它能夠把.inc文件也當作php文件來處理。否則,黑客們也許會猜到您的頭文件名,然后用瀏覽器把頭文件內容以純文本格式顯示出來。此時如果您的頭文件中有些機密信息(如數據庫口令等)那就糟糕了。
那么,您用頭文件來做什么呢?很簡單!把對所有程序都通用的那些內容放到頭文件里。象html文件頭啦,腳注啦,數據庫連接代碼啦,還有您自己定義的一些函數什么的。把下面的文字拷貝到一個文件中,保存為header.inc。
<?php$db = mysql_connect("localhost", "root");mysql_select_db("mydb",$db);?><html><head><title><?php echo $title ?></title></head><body><center><h2><?php echo $title ?></h2></center>
然后再創建另外一個文件,名字是footer.txt,該文件可以包含一些程序結束時用到的一些文字和標記。
現在,我們再來創建一個文件,這個文件里面是真正的php程序代碼。試一下下面的代碼,當然,您要確認mysql數據庫服務器正在運行。
<?php$title = "hello world";include("header.inc");$result = mysql_query("select * from employees",$db);echo "<table border=1>/n";echo "<tr><td>名字</td><td>職位</tr>/n";while ($myrow = mysql_fetch_row($result)) {printf("<tr><td>%s %s</td><td>%s</tr>/n", $myrow[1], $myrow[2], $myrow[3]);}echo "</table>/n";include("footer.inc");?>
看到發生了什么事了嗎?頭文件里的內容被合并到程序中,php把所有的代碼都執行了一遍。注意在包含header.inc頭文件之前$title是如何定義的。在header.inc中的代碼可以訪問到它的值。這樣,網頁的標題就被改掉了。現在,您可以在任何程序中使用header.inc頭文件了,您所要做的不過是在每個主程序中為$title變量取一個合適的值。
頭文件、html、條件判定語句,還有循環語句,這些東西加在一些,您就可以用最簡練的代碼,寫出功能各異的各種復雜程序來。在與函數同時使用時,頭文件更能發揮它的效力,我們后面就會看到。
接下去,我們會介紹精彩的部分:數據校驗。>>
二、 數據校驗
想象一下這樣的情形:我們把數據庫都設計妥當了,現在請用戶輸入信息來寫到數據庫中去。假設您有一個字段是要求數字類型的信息,比如價格;而某個可愛的用戶,卻在這一欄里輸入了文字信息,使得您的應用程序的執行過程出現了故障。對您在sql語句中提供的文字類型的數據,mysql數據庫拒不接受,并向您提出了“嚴正抗議”。
怎么辦呢?您要用數據校驗來防止以上狀況發生。
簡單地講,數據校驗是指我們對數據(通常是用戶經由html表格傳過來的)進行檢查,看看它是否遵從一定的規則。規則可以是多種多樣的,比如某一數據元素不能為空,或者要求某一數據項的內容必須滿足一定的要求(例如前面的例子中要求必須是數字而不是文字,或者要求電子郵件地址中一定要包含一個“@”字等等)。
數據校驗既可以在服務器一端作,也可以在客戶端來作。php是用來作服務器一端的數據校驗的,而javascript或其他客戶端腳本編程語言則能夠提供客戶端的數據校驗功能。本文說的是php,所以我們在這里著重介紹服務器端的校驗。如果您想找一些現成的、在客戶端運行的數據較驗程序,那您可以去網猴程序庫看看。
暫時把數據庫放在一邊不談,我們先來說說php的數據校驗方法。如果您愿意(或者說,您想記錄我們要校驗的那些數據的話),您可以在前面所建的員工數據庫的里加入其他字段,很簡單,用mysql的alter 語句就行了。
有好幾個php功能都可以用來作數據校驗的工作,有些很簡單,有些則復雜一些。其中strlen()是比較簡單的一個函數,它能夠告訴我們一個變量的長度。
更復雜一點兒的是ereg(),這個函數可以處理完整的常規表達式來進行復雜的校驗。我不想就常規表達式講得太深,因為許多書都是專門寫這個問題的。不過我會在下一頁中給出一些簡單的例子。
我們先從一個簡單的例子開始吧。下面這個程序要檢查一個變量是否存在。
<html><body><?phpif ($submit) {if (!$first || !$last) { $error = "對不起,您必須填寫所有的欄目!";} else {// 處理表格輸入內容echo "謝謝!";}}if (!$submit || $error) {echo $error;?><p><form method="post" action="<?php echo $php_self ?>">第一欄: <input type="text" name="名" value="<?php echo $first ?>"><br>第二欄: <input type="text" name="姓" value="<?php echo $last ?>"><br><input type="submit" name="submit" value="輸入信息"></form><?php} // if結束?></body></html>
這段程序中關鍵的地方是嵌套的條件判定語句。第一層檢查用戶是否按了發送數據的按鈕。如果是,程序接著檢查$first和$last兩個變量是否都存在。那個 || 符號表示“或”,而 ! 符號表示“非”。那一句程序用一般語言描述就是“如果$first不存在或者$last不存在,那么就把 $error變量置成下面的值。”
接下來,我們再進一步,檢查一段文字的長度。這對用戶口令的檢查是很有必要的,因為您不想讓某些懶惰的用戶輸入只有一、兩個字的口令,可能會要求他們輸入六位長的口令。
我們已經講到strlen()這個函數了。它只是簡單地返回一個數字,該數字等于被測變量中所包含的字符個數。這里,我修改一下上面的程序,檢查一下$first與$last的長度。
<html><body><?phpif ($submit) {if (strlen($first) < 6 || strlen($last) < 6) { $error = "對不起,您必須填寫所有欄目!";} else {// 處理表格輸入內容echo "謝謝!";}}if (!$submit || $error) {echo $error;?><p><form method="post" action="<?php echo $php_self ?>">第一欄: <input type="text" name="名" value="<?php echo $first ?>"><br>第二欄: <input type="text" name="姓" value="<?php echo $last ?>"><br><input type="submit" name="submit" value="輸入信息"></form><?php} // if結束?></body></html>
您可以執行一下這段程序,輸入六個字或少于六個字的內容。這種校驗很簡單,但很有效。>>
三、 處理常規表達式
我們稍微講講用ereg()和eregi()兩個函數處理常規表達式。前面我已經提過,這些函數有的很簡單,有的很復雜,看您的實際需要而定。
使用常規表達式,您可以對一個字符串進行檢查,搜索其中的一些結構模式,判定這些模式是否滿足您的規定。最普遍的用法包括檢查電子郵件地址是否有效(當然,即使這種辦法判定有效,也不能保證郵件地址真的存在)。
我們在這里不細究常規表達式的復雜細節了,僅僅給出幾個實例。您可以使用上一頁中用過的表格 - 把相應的程序代碼復制過來,添加到下面的代碼段中,就可以看到它是怎樣工作的。
首先,我們要確保表格中各欄只能輸入字母。下面的常規表達式在用戶輸入一個或多個小寫字母時判定為真,而輸入數字是不允許的:
if (!ereg("[a-z]", $first) || !ereg("[a-z]", $last)) {
現在我們更進一步,檢查字符串的長度是否是四到六位字符長。用[[:alpha:]]是檢查字符是不是字母的簡單方式。大括號內的數字檢查字符個數。還要說明的是,^ 和 $ 分別代表字符串的開始和結束。
if (!ereg("^[[:alpha:]]{4,6}$", $first) || !ereg("^[[:alpha:]]{4,6}$", $last)) {
最后,我們來構造一個常規表達式,來檢驗電子郵件地址的有效性。這種檢驗方式的效果已經引發了相當多的討論。沒有什么東西是十全十美的,不過我下面給出的這段程序還是十分奏效的。
我這段寶貝程序是從php郵件討論組上得來的。那可是個好去處 - 常去看看吧。不錯,這段程序看起來是有點亂糟糟的。
if (!ereg('^[-!#$%&/'*+//./0-9=?a-z^_`a-z{|}~]+'.'@'.'[-!#$%&/'*+///0-9=?a-z^_`a-z{|}~]+/.'.'[-!#$%&/'*+//./0-9=?a-z^_`a-z{|}~]+$', $last)) {
別花太多時間來細究這段代碼了,還是先到下一頁內容吧。>>
四、 簡便方法
前面的常規表達式怎么樣?很有意思,是吧?要是在每個需要檢查電子郵件地址的程序里都寫上這么一段程序,那才真叫有意思呢?!想想看吧,得寫那么亂七八糟的一段程序,還得寫上那么多遍!...不過,當然了,還有更簡便的方法。
還記得前面我們學過的頭文件嗎?它能讓我們寫一段程序,象是這個電子郵件地址的檢查程序,然后把這段程序包含進多個程序里面去。這樣,我們要改寫這段程序時,只須改動一處就行了,不用修改多個文件。
但是,要做到這一點,我們必須用到函數。
我們已經用過很多次函數了。每次我們查詢數據庫或檢查字符串長度時,我們都是用函數來做的。這些函數是php自帶的。如果您是位熱心的程序員,您可以用自己編寫的函數來擴充php本身的功能。但對本教程而言,這部分內容是太過高深了一點。我們要創建的函數不是那一種,而是寫在php腳本程序內部的函數。
函數就是一段程序代碼,我們可以把一個或多個值傳給這段代碼,然后這段代碼會處理我們傳給它的數據并返回一個值。根據實際需要,函數可以很簡單,也可以十分復雜。但是只要我們傳進去一個數,然后能得到一個數,您管它里面有是復雜還是簡單呢!這就是函數的可愛之處。
php里的函數與c語言里的函數表現差不多。當我們定義函數時,必須指明函數需要接收什么樣的數據。一開始好象不太好理解為什么它要接收數據進去,不過這樣可以防止發生一些怪異的問題。函數之所以能做到這一點,是因為函數里面的變量都是私有變量,也就是說,它只在該函數內部存在。例如,您在程序中有一個變量叫$myname,如果您創建了一個函數,想讓這個函數也使用那個$myname變量(值也相同),那是不行的。您可以在函數內部創建一個變量,名字也叫$myname,這兩個變量可以各平相處,而各自取不同的值。不過我可不建議您這么做!您如果真的這么做了,等半年后您再來修改這樣的程序時,您可能就會被弄糊涂了。
那我們現在就來創建一個函數,先來個簡單的。我們要給它取個名字,指定它要接收什么的變量。在調用這個函數之前,我們還得定義這個函數。
<html><body><?phpfunction addnum($first, $second) {$newnum = $first + $second;return $newnum;}echo addnum(4,5);?></body></html>
這就行了!首先,我們創建了第一個自己的函數。我們定義了兩個新變量,$first和$second,注意它們是怎樣被定義的。在調用這個函數時,要給這兩個變量按它們出現的順序賦好值 - 4賦給$first,5賦給$second。然后我們簡單地把這兩個數加在一起,返回結果。“返回”在這里的意思是把結果送回去。在程序最后部分我們把數字9顯示出來。
我們再來創建一個函數,讓它對我們的數據庫應用有點幫助。一個能妥善處理錯誤的函數怎么樣?試試下面的程序:
<html><body><?phpfunction do_error($error) {echo "噢,好象有點兒問題...<br>";echo "系統報告的錯誤是:$error./n<br>";echo "最好是暫時關閉網站并通知系統管理員。";die;}if (!$db = @mysql_connect("localhost","user", "password")) {$db_error = "無法連接到mysql數據庫";do_error($db_error);}?></body></html>
在運行程序之前,試試關閉mysql數據庫,或使用錯誤的用戶名或口令。您會看到友好的、有用的錯誤信息 。細心的朋友會注意到在mysql_connect()函數之前的那個@符號。它會抑制系統錯誤信息,使得程序只能從do_error()函數那里得到有關的錯誤信息。您還會注意到,我們可以把一個在別處定義的變量作為參數傳給函數,而不是在調用時直接賦一個值。
還記得我過函數使用的是私有變量吧?這話說得不完全對。事實上,您可以讓函數訪問到函數外面的變量。您可能要寫一個函數,用它來查詢數據庫,然后把結果顯示在多個網頁中。您不想每次都把數據庫連接標識都傳給函數。在這種情況下,您可以把連接標識定義成一個全局的變量。例如:
<html><body><?phpfunction db_query($sql) {global $db;$result = mysql_query($sql,$db);return $result;}$sql = "select * from mytable";$result = db_query($sql);?></body></html>
這是個很簡單的函數,但重要的是,您在調用這個函數時,不必傳遞$db變量 - 您可以通過 global這個字使得函數可以訪問到該變量。在這條語句中您可以定義多個全局變量,各個全局變量之間用逗號隔開。
最后,您可以使用可選參數,這樣看起來您已經是真正的專家了。這里面關鍵的一點是,在函數中定義參數時要給它指定一個缺省值。然后您在調用這個函數時,如果不為該參數變量指定其他值,那么函數會自動把缺省值賦給這個變量。如果您指定了其他值,那么缺省值就不起作用了。
不太明白?比方說,您在連接數據庫時,幾乎總是連接到相同的服務器,并且使用相同的用戶名和口令。不過有時候,您也需要連接到其他的服務器。看看下面的程序:
<html><body><?phpfunction db_connect($host = "localhost", $user="username", $pass="graeme") {$db = mysql_connect($host, $username, $password);return $db;}$old_db = db_connect();$new_host = "site.com";$new_db = db_connect($new_host);?></body></html>
很“酷”是不是?在定義函數時,函數內部用到的變量也定義好了。第一次調用這個函數時,全部參數變量都是用的缺省值。第二次調用時,服務器名變了,而用戶名和口令沒有變。真是太棒了!
想想您在什么地方還能用到函數。您可以用函數來作數據校驗,來完成常用的功能,等等。在對web網頁上顯示的文字作處理時,我用到了很多函數。我可以一次完成對文字的檢查、解析和修改,來加入換行符和html標記等。
現在,剩下的就是我要給您的一些忠告了。>>
五、進階技巧
談起數據庫開發,我們有很多東西要學。如果您還沒有學習過怎樣進行數據庫設計,和怎樣在不同的平臺上可靠地運行數據庫,那么請您趕快去找本這方面的好書來讀一讀。這方面的能力會帶給您無法估量的好處,從長遠的眼光看,它會為您節省大量的時間與精力。還有,認真學學mysql。這是一個復雜而有趣的數據庫,有很多不錯的文檔。學學數據庫的表結構、數據類型,還有sql。如果您真正掌握了sql,您可以完成相當多的實際工作。
最后,還有php。您想要的一切幾乎都可以在php的網站上找到,包括全面的文檔、郵件討論組的討論內容、程序代碼庫,等等。學習php的一個絕好的辦法是研究用戶手冊中給出的實例,并查閱網上的代碼。網友們發表的代碼包括許多函數和類,您可以在自己的程序中直接使用,而不必自己從頭來過。另外,如果您遇到問題,郵件討論組是一個非常值得利用的資源。php的開發人員自己也會參加郵件討論組,還有許多經驗豐富的高手們,他們都可以幫助您解決問題。
祝您編程順利,一切順利