設定
繼續後面的内容之前,需要對 MySQL 做一點準備工作。需要建立資料庫、添加表和建立通路它的新使用者。
在 MySQL 控制台中輸入以下内容:
create database workflow;
use workflow;
create table users (id int auto_increment primary key, username
varchar(50), email varchar(255), password varchar(50));
show tables;
最後的結果看起來類似于:
+--------------------+
| Tables_in_workflow |
+--------------------+
| users |
+--------------------+
1 row in set (0.00 sec)
最後添加新使用者
wfuser
,密碼為
wfpass
:
GRANT ALL PRIVILEGES ON *.* TO 'wfuser'@'localhost'
IDENTIFIED BY 'wfpass' WITH GRANT OPTION;
然後我們來使用這個資料庫。
連接配接 MySQL
如果不與某種形式的資料庫互動,那麼建立任何較大的 Web 應用程式基本上是不可能的。在這個示例應用程式中,我們将使用 MySQL 資料庫儲存使用者名和密碼資訊。這一節将在注冊頁面中添加必要的功能,以檢查送出的使用者名是否惟一,如果是惟一的,則将其添加到表中。還可以檢視已經顯示在資料庫中的資訊。最終我們将建立應用程式登入頁面。
首先要連接配接到資料庫。PHP 有一些函數完全是用于處理 MySQL 資料庫的,這一節中将用到它們。
第一步是建立一個函數,以連接配接到 設定 一節中建立的工作流資料庫:
...
return $message;
}
function db_connect($user='wfuser',
$password='wfpass', $db='workflow'){
mysql_connect('localhost', $user, $password)
or die('I cannot connect to db: ' . mysql_error());
}
foreach ($_POST as $key=>$value) {
echo "<p>".$key." = " . $value . "</p>";
}
...
if (validate($_POST) == "OK") {
echo "<p>Thank you for registering!</p>";
db_connect();
} else {
echo "<p>There was a problem with your registration:</p>";
...
這裡建立了一個函數
db_connect()
,該函數将嘗試打開 PHP 和 MySQL 資料庫之間的連接配接。要注意該函數的定義,其中包含了一些參數值。這些是預設值,也就是說,如果不提供使用者名、密碼和資料庫名,那麼 PHP 将使用這些值(實際上很快就要這樣做。)
該函數嘗試連接配接到本地機器
localhost
上的資料庫。要注意的是,在這個例子中,“本地機器”指的是對 PHP 伺服器而言的本地機器,是以,本地機器指的是 Web 伺服器而不是客戶機。
如果 PHP 打不開連接配接,那麼處理将終止(或者死掉),PHP 隻顯示一條消息,說明遇到了什麼情況。
假設一切正常,那麼該連接配接将一直處于打開狀态,直到您關閉它,或者完成該頁面的處理。發出的其他所有資料庫指令都被定向到該連接配接。
最後還需要調用該函數來執行這些操作。
選擇資料庫
一個 MySQL 資料庫伺服器可能有多個資料庫,是以打開到伺服器的連接配接之後,還需要指定連接配接的資料庫:
...
function db_connect($user='wfuser',
$password='wfpass', $db='workflow'){
mysql_connect('localhost', $user, $password)
or die('I cannot connect to db: ' . mysql_error());
mysql_select_db($db);
}
...
現在,這個函數可以用于連接配接本地伺服器上的任何 MySQL 資料庫。實際上,該函數的一大優點就是這一點,從某種意義上說,這個優點是與資料庫無關的。您不僅可以改變資料庫的名稱,還可以更改将要通路的資料庫類型,而且所有修改都在這個函數中完成。
現在可以準備插入使用者資料了。
插入記錄
現在可以向前面建立的使用者表中添加資料了。為此需要建立一個向該表插入資料的 SQL 語句,然後執行該語句。
該語句的形式如下:
insert into users (username, email, password) values
('roadnick', '[email protected]', 'supersecretpassword')
如果在建立表時特别注意,您可能會奇怪
id
列是幹什麼的。可以指定第一列為
AUTO_INCREMENT
,是以如果不去考慮它(正像我們這裡所做的那樣),那麼 MySQL 将自動向其中填入下一個可用的整數。是以,您在這裡必須做的事情是,使用使用者送出的資料替換占位符,并執行以下語句:
...
if (validate($_POST) == "OK") {
echo "<p>Thank you for registering!</p>";
db_connect();
$sql = "insert into users (username, email, password) values
('".$_POST["name"]."', '".$_POST["email"]."', '".$passwords[0]."')";
$result = mysql_query($sql);
if ($result){
echo "It's entered!";
} else {
echo "There's been a problem: ".mysql_error();
}
} else {
echo "<p>There was a problem with your registration:</p>";
...
注意,調用
mysql_query()
函數時傳回的值儲存在
$result
變量中。如果操作成功,則該值将是 true,如果出現問題,則為 false。然後可以使用該值作為 if-then 語句的表達式,根據結果執行不同的操作。
如果出現問題,MySQL 将為
mysql_error()
函數設定一個傳回值,然後可以将這個值輸出到頁面。
現在已經在資料庫中添加了資訊,下一步則是檢視存儲的資訊。
選擇記錄
現在可以向資料庫中添加資料了,但是如何知道使用者名是否惟一呢?目前還不知道,但是可以通過在執行插入之前檢查使用者表來加以補救:
...
if (validate($_POST) == "OK") {
echo "<p>Thank you for registering!</p>";
db_connect();
$sql = "select * from users where username='".$_POST["name"]."'";
$result = mysql_query($sql);
if (!$result) {
$sql = "insert into users (username, email, password) values
('".$_POST["name"]."', '".$_POST["email"]."', '".$passwords[0]."')";
$result = mysql_query($sql);
if ($result){
echo "It's entered!";
} else {
echo "There's been a problem: ".mysql_error();
}
} else {
echo "There is already a user with that name: <br />";
$sqlAll = "select * from users";
$resultsAll = mysql_query($sqlAll);
}
} else {
echo "<p>There was a problem with your registration:</p>";
...
首先建立一個 SQL 語句,該語句将選出擁有與打算插入的使用者名比對的使用者名的所有記錄。與插入語句一樣,也可以對資料庫執行該語句。如果該語句傳回的結果不為空,則
mysql_query()
傳回一個結果為 true 的值,否則傳回 false。
現在我們不希望存在這樣的使用者名,是以希望
$result
的值為 false。但如果使用的是 if-then 語句的話,那麼希望獲得的将是 true 語句,而不是 false 語句。是以要使用取反運算符,即歎号,其含義為“如果該值的反是 true,則應該做什麼”,在這裡,所謂做什麼是指将資料插入資料庫。
但是,如果
$result
為 true,那麼該怎麼做呢?如果
$result
的反是 false,則執行 else 語句。最後我們将列出已有的使用者名和郵件位址,是以,首先要建立并執行這樣的 SQL 語句。
然後是檢索結果。
檢索結果
當然,在現實中,如果輸入了已經存在的使用者名,則絕對不需要顯示已有的使用者名,不過,在這裡這樣做是為了說明如何完成這類工作。
上一節中建立了一個 SQL 語句,以便從使用者表中選擇所有記錄,并把結果存放在
$resultsAll
變量中。現在要從該變量中檢索資料:
...
} else {
echo "There is already a user with that name: <br />";
$sqlAll = "select * from users";
$resultsAll = mysql_query($sqlAll);
$row = mysql_fetch_array($resultsAll);
echo $row["username"]." -- ".$row["email"]."<br />";
}
...
檢索資料的第一步是從
$resultsAll
中取出一行,它實際上是表示整個資料集的資源。
mysql_fetch_array()
函數正如其名稱所訓示的那樣,傳回包含某一行中資料的關聯數組。鍵和列名相同,是以,通過從
$row
數組中請求适當的值,很容易輸出這一行中的資料。
不過該例中隻有一行,如何通路所有資料呢?
檢視所有的結果:
while
循環
如果在第一次檢索中,至少有一行可供檢索,那麼在 if-then 語句(或者後面使用的 while 語句)中,
$row
将顯示為 true。當 PHP 遇到
while
(
$row
) 語句時,它會說,“哦,該表達式的值是 true,那麼執行這一段代碼吧。”于是輸出這一行資料,然後再提取另一行,又回到循環的頂端。
...
} else {
echo "There is already a user with that name: <br />";
$sqlAll = "select * from users";
$resultsAll = mysql_query($sqlAll);
$row = mysql_fetch_array($resultsAll);
while ($row) {
echo $row["username"]." -- ".$row["email"]."<br />";
$row = mysql_fetch_array($result);
}
}
...
如果檢索另一行成功,那麼
$row
将再次為 true,循環再次執行。如此反複,直到沒有剩餘的行為止,
mysql_fetch_array()
傳回 false。現在,PHP 知道要跳出循環執行腳本中剩下的語句。
順便說一下:如果忘掉最後一步,即檢索另一行,那麼
$row
将一直為 true,伺服器不停地運作該循環,直到記憶體溢出或者逾時為止。是以,建立這類循環時,首先應該添加的語句就是遞增要周遊的對象。
關閉資料庫連接配接
繼續下一步之前,一定要關閉打開的資料庫連接配接:
...
if (validate($_POST) == "OK") {
echo "<p>Thank you for registering!</p>";
db_connect();
$sql = "select * from users where username='".$_POST["name"]."'";
$result = mysql_query($sql);
if (!$result) {
...
}
mysql_close();
} else {
...
現在就等着整理了……