【IT168 PHP开发】如果你来这里是想学习基本的PHP4或者PHP5知识,那这就是为你准备的,开始享受吧!
PHP最引入注目的特征之一就是它对多种数据库管理系统(包括MySQL、PostgreSQL、Oracle和Microsoft Access)的支持。依靠这种支持,PHP开发人员可以创建复杂的数据驱动的Web应用而只需要竞争对手所需时间和成本的一部分。没有其他语言比PHP语言对MySQL的长期支持更清楚地了,MySQL是一种非常快速、非常可靠以及功能非常丰富的开源数据库管理系统。
通过PHP和MySQL数据库的结合使用,开发人员可以从商业数据库许可费的极大地节约中受益。而且,因为PHP和MySQL均为开源项目,所以当你一起使用它们两个时,你就会知道你正在使得最新技术可用。
好了,让我们言归正传。
在本篇中,我将向你展示如何使用PHP从一个数据库中提取数据,然后使用该数据以动态地构建一个Web页面。为了能够尝试本教程中的例子,你需要一个可工作的MySQL,你可以从MySQL的网站http://www.mysql.com/获得该MySQL安装。如果你有一些SQL(结构化查询语言,用于与数据库服务器交互作用的语言)的知识,那么你会发现它是有帮助的,但并不是必须的。
构建块
为了将MySQL和PHP一起使用,你的PHP构造必须包含对MySQL的支持。在UNIX平台上,这通过在UNIX平台上构造PHP时将with-mysql选项添加至配置脚本—然后将PHP指向MySQL客户端库来完成。在Windows平台上,MySQL客户端库已经构建在PHP 4内部并且被默认激活了。在PHP 5中,预先生成的.dll文件被包含在Windws版本的发布中。
请在下面的网址中阅读更多关于这方面的信息:http://www.php.net/manual/en/ref.mysql.php。
Unix的用户应该注意到PHP 4装有一系列的MySQL客户端库,该等客户端库默认情况下是激活的;然而,PHP 5由于许可证颁发的原因不再捆绑这些库,因此你需要自己去获得、安装以及激活这些库。它们包含在MySQL的分发中,而且当你安装MySQL时它们会自动安装。为了激活MySQL扩展ext/mysql,请在PHP配置脚本中添加–with-mysql选项。
关于这一变化的更多的信息,请阅读:http://www.php.net/manual/en/faq.databases.php#faq.databases.mysql.php5。
最后(好像所有上述还不是十分的令人迷惑),PHP 5也提供了一个新的MySQL 扩展(被称为ext/mysqli(改良的MySQL))。你可以使用该新扩展来访问MySQL4.1.2或者更高的MySQL版本中的新特征,从而获取改良后的速度和安全方面的益处。为了在UNIX平台上激活该扩展,请在PHP配置脚本中添加–with-mysqli选项,然后将PHP指向mysql_config程序,该程序与MySQL4 .1及以上版本一起提供。对Windows用户来说,ext/mysqli提前构造好的版本包含在win32下的PHP分发中。
阅读更多关于这方面的内容,请访问:http://www.php.net/manual/en/ref.mysqli.php。
为了确定你需要哪个扩展,请使用下列规则:
•如果你需要使用MySQL 4.1.2或者更高的版本的新特征,或者你正在使用老版本的MySQL但是仍然想从新扩展的速度/安全方面的改良上受益,那么请使用ext/mysqli库。
•如果你不在上述所列的类别范围之内,或者不知道我在讲什么,那么请使用常规的ext/mysql库。
倘若你想知道,该教程包含ext/mysql和ext/mysqli两部分,因此你实际上用一个的价钱得到了两个。请继续阅读本教程,让我向你介绍MySQL。
数据库表的操作
每个MySQL数据库是由一或多个表组成的。这些将数据组织成行或列的表格是将数据进行组织的表格。
下面是一个典型表格看起来的样子的例子:
+----+-----------+----------+
| id | country | animal |
+----+-----------+----------+
| 1 | America | eagle |
| 2 | China | dragon |
| 3 | England | lion |
| 4 | India | tiger |
| 5 | Australia | kangaroo |
| 6 | Norway | elk |
+----+-----------+----------+
就像你所看到的,一个表格将数据分为多行,每行都有一个新条目(或记录)。每行数据又进一步分解成单元格(或字段),每个单元格包含了一个用于数据特定属性的值。举例而言,如果你考虑国家“India”的记录,你会看到该记录被清楚的分割成用于记录号、国家名和民族动物的独立的字段。
表格内的行并没有按照特定的顺序来排列 (它们可以按照字母表顺序、按照号码、按照名字或按照你指定的任意其他准则来排序)。因此,有必要用某种方法来识别表中的一特定纪录。在上述例子中,每个记录是用一个唯一的数字所标示的;这个唯一的字段被称作该表的关键字段。
你使用结构化查询语言SQL来与MySQL服务器交互作用,然后告诉其创建表格、将某个字段标记为关键字段、插入记录、编辑记录、检索记录,等等。基本上,涉及操作数据或数据库的任何活动。为了理解它是如何工作的,请研究下述SQL代码,该代码创建了上述表格:
CREATE DATABASE testdb; CREATE TABLE `symbols` ( `id` int(11) NOT NULL auto_increment, `country` varchar(255) NOT NULL default '', `animal` varchar(255) NOT NULL default '', PRIMARY KEY (`id`) ) TYPE=MyISAM; INSERT INTO `symbols` VALUES (1, 'America', 'eagle'); INSERT INTO `symbols` VALUES (2, 'China', 'dragon'); INSERT INTO `symbols` VALUES (3, 'England', 'lion'); INSERT INTO `symbols` VALUES (4, 'India', 'tiger'); INSERT INTO `symbols` VALUES (5, 'Australia', 'kangaroo'); INSERT INTO `symbols` VALUES (6, 'Norway', 'elk');
你可以通过MySQL命令行客户端程序以交互式或非交互式的模式来输入这些命令,该命令行客户端程序可以通过在你的shell命令解释器或者DOS窗口导航到mysql/bin目录然后键入(不需要“;”,因为这是shell命令)mysql或者mysql db_name(如果你打算选择使用一个已经存在的数据库)来运行。SQL非常类似于英语口语,因此不会花去你太多的时间去学会它。不要试图将那些反引号运算符转变为单引号标记。
一旦数据被导入,运行一条快捷的查询语句以检查所有的一切都工作的很好:
mysql> SELECT * FROM `symbols`;在英语中,上述查询表示:“向我展示名为symbols表格的所有记录“。如果你看到的结果和上面的一样,那么很好继续下去!
+----+-----------+----------+
| id | country | animal |
+----+-----------+----------+
| 1 | America | eagle |
| 2 | China | dragon |
| 3 | England | lion |
| 4 | India | tiger |
| 5 | Australia | kangaroo |
| 6 | Norway | elk |
+----+-----------+----------+
6 rows in set (0.06 sec)
简单操作数据库
现在,让我们使用PHP来做同样的事情。自一开始,你就可以使用PHP来建立数据库,但是因为我们的数据库已经存在,所以我们将简单地对数据库“testdb”发出一条SELECT查询语句,然后以HTML页面显示结果:
<html> <head> <basefont face="Arial"> </head> <body> <?php // set database server access variables: $host = "localhost"; $user = "test"; $pass = "test"; $db = "testdb"; // open connection $connection = mysql_connect($host, $user, $pass) or die ("Unable to connect!"); // select database mysql_select_db($db) or die ("Unable to select database!"); // create query $query = "SELECT * FROM symbols"; // execute query $result = mysql_query($query) or die ("Error in query: $query. ".mysql_error()); // see if any rows were returned if (mysql_num_rows($result) > 0) { // yes // print them one after another echo "<table cellpadding=10 border=1>"; while($row = mysql_fetch_row($result)) { echo "<tr>"; echo "<td>".$row[0]."</td>"; echo "<td>" . $row[1]."</td>"; echo "<td>".$row[2]."</td>"; echo "</tr>"; } echo "</table>"; } else { // no // print status message echo "No rows found!"; } // free result set memory mysql_free_result($result); // close connection mysql_close($connection); ?> </body> </html>
下面是程序结果:

正如你可以看到的那样,使用PHP从数据库得到数据包括几个步骤,每个步骤实际上都是预定义的PHP函数。下面让我们仔细研究每个步骤。
1. 要做的第一件事就是指定一些在建立到数据库服务器的连接时所需要的重要信息。这些信息包括访问数据库所需要的服务器名称、用户名称和密码以及要查询的数据库名称。这些值都被设置在常规PHP变量。
<?php $host = "localhost"; $user = "test"; $pass = "test"; $db = "testdb"; ?>
2. 为了开始和MySQL数据库服务器通信,你需要打开一个到该服务器的连接。在PHP和数据库服务器之间的所有通信都通过这条连接而发生。
为了初始化该连接,PHP提供了mysql_connect()函数:
<?php $connection = mysql_connect($server, $user, $pass); ?>
mysql_connect()函数中的所有参数都是可选的,但是你通常需要三个参数以在你自己的机器之外使用:数据库服务器名称,用户名称和密码。如果数据库服务器和Web服务器运行于同一台物理机器上,那么你可以使用“localhost”作为数据库服务器名称(其实际上是由PHP提供的缺省值)。
mysql_connect()函数返回一个“连接标识符”,该“连接标识符”存储于变量$connection中。这个标识符在与数据库通信时使用。
3. 一旦你和数据库建立了连接,那你必须用函数mysql_select_db()来选择一个数据库以供使用。
<?php mysql_select_db($db) or die ("Unable to select database!"); ?>
该函数必须被传递一个用于所有后续查询的数据库名称。这里的第二个可选参数是一个连接标识符;如果没有指定标识符,那么假定最后打开的连接。如果你同时有两个或两个以上打开的数据库连接,那么将连接标识符指定为mysql_select_db()函数的第二个参数(且实际上指定为脚本中所有其他mysql_*函数的第二个参数)以便于PHP不会困惑于哪里使用哪个连接,这会是一个好注意。
4. 下一个步骤就是创建查询然后执行它。该步骤是用mysql_query()函数来完成的。
<?php $query = "SELECT * FROM symbols"; $result = mysql_query($query) or die ("Error in query: $query. ".mysql_error()); ?>
该函数也需要两个参数:查询字符串和用于连接的连接标识符。再次说明,如果没有指定连接标识符,那么使用最后一个打开的连接。根据查询是否成功,函数返回真或假;查询失败可以通过…或die()语句来捕获,而mysql_error()函数可用于显示对应的错误信息。
5. 如果mysql_query()成功,那么查询返回的结果集存储于变量$result中。这取决于你的查询,该结果集可包含一或多行(列)数据。你可以用不同的PHP函数(其包括这里用到的函数mysql_fetch_row(),该函数取得一行数据作为一称作$row的数组。)来检索结果集中的特定子集。该行中的字段然后就可以使用标准的PHP数组符号来访问。每次你调用mysql_fetch_row()时,结果集中的下一条记录被返回。这使得mysql_fetch_row()函数非常适用于while()或者for()循环中。
<?php if (mysql_num_rows($result) > 0) { while($row = mysql_fetch_row($result)) { echo "<td>".$row[0]."</td>"; echo "<td>".$row[1]."</td>"; echo "<td>".$row[2]."</td>"; } } ?>
请注意,对函数mysql_fetch_row()的调用被包含在一条条件测试语句中,该条件测试语句首先检查看是否有任意行被返回。该信息由mysql_num_rows()函数来提供,该函数包含了查询所返回的行数。很显然,你只能将该函数用于返回数据的查询(比如,SELECT或者SHOW语句)。它不适合用于INSERT、UPDATE、DELETE或类似的查询中。
这里有若干其他函数可代替mysql_fetch_row(),它们将会在稍后被解释说明。
6. 最后,因为查询之后返回的每个结果集都将占用内存,所有使用函数mysql_free_result()释放使用过的内存是一个好注意。在结果集被释放后,如果没有进一步的查询运行,那么你可以用mysql_close()函数来关闭到MySQL服务器的连接。
<?php mysql_free_result($result); mysql_close($connection); ?>
你也可以使用PHP的mysql_fetch_row()和list()函数来获取值的一个简单数组,然后将这些值赋给不同变量---这是上述章节中的技术的一个变化。请看(只有while()循环改变):
<html> <head> <basefont face="Arial"> </head> <body> <?php // set server access variables $host = "localhost"; $user = "test"; $pass = "test"; $db = "testdb"; // open connection $connection = mysql_connect($host, $user, $pass) or die ("Unable to connect!"); // select database mysql_select_db($db) or die ("Unable to select database!"); // create query $query = "SELECT * FROM symbols"; // execute query $result = mysql_query($query) or die ("Error in query: $query. ".mysql_error()); // see if any rows were returned if (mysql_num_rows($result) > 0) { // yes // print them one after another echo "<table cellpadding=10 border=1>"; while(list($id, $country, $animal) = mysql_fetch_row($result)) { echo "<tr>"; echo "<td>$id</td>"; echo "<td>$country</td>"; echo "<td>$animal</td>"; echo "</tr>"; } echo "</table>"; } else { // no // print status message echo "No rows found!"; } // free result set memory mysql_free_result($result); // close connection mysql_close($connection); ?> </body> </html>
在这个例子中,list()函数用于将结果集中的不同元素赋值给PHP变量,在重现该页面时接着使用该PHP变量。
你可以使用PHP的mysql_fetch_assoc()函数来将每行描述为字段-值对的关联数组(上面所用技术的一点较小变化)。
<html> <head> <basefont face="Arial"> </head> <body> <?php // set server access variables $host = "localhost"; $user = "test"; $pass = "test"; $db = "testdb"; // open connection $connection = mysql_connect($host, $user, $pass) or die ("Unable to connect!"); // select database mysql_select_db($db) or die ("Unable to select database!"); // create query $query = "SELECT * FROM symbols"; // execute query $result = mysql_query($query) or die ("Error in query: $query. ".mysql_error()); // see if any rows were returned if (mysql_num_rows($result) > 0) { // yes // print them one after another echo "<table cellpadding=10 border=1>"; while($row = mysql_fetch_assoc($result)) { echo "<tr>"; echo "<td>".$row['id']."</td>"; echo "<td>".$row['country']."</td>"; echo "<td>".$row['animal']."</td>"; echo "</tr>"; } echo "</table>"; } else { // no // print status message echo "No rows found!"; } // free result set memory mysql_free_result($result); // close connection mysql_close($connection); ?> </body> </html>
请注意,在这个例子中,字段值是通过使用字段名称而不是索引值来访问的。
然而,在上述所有可供选择的方法中,我最喜欢的函数是mysql_fetch_object()函数,该函数以一个具有与字段名称对应的属性的对象(还记得在第七章中所讲到它们吗?)而返回每一行。
<html> <head> <basefont face="Arial"> </head> <body> <?php // set server access variables $host = "localhost"; $user = "test"; $pass = "test"; $db = "testdb"; // open connection $connection = mysql_connect($host, $user, $pass) or die ("Unable to connect!"); // select database mysql_select_db($db) or die ("Unable to select database!"); // create query $query = "SELECT * FROM symbols"; // execute query $result = mysql_query($query) or die ("Error in query: $query. ".mysql_error()); // see if any rows were returned if (mysql_num_rows($result) > 0) { // yes // print them one after another echo "<table cellpadding=10 border=1>"; while($row = mysql_fetch_object($result)) { echo "<tr>"; echo "<td>".$row->id."</td>"; echo "<td>".$row->country."</td>"; echo "<td>".$row->animal."</td>"; echo "</tr>"; } echo "</table>"; } else { // no // print status message echo "No rows found!"; } // free result set memory mysql_free_result($result); // close connection mysql_close($connection); ?> </body> </html>
这里,每个$row对象被创建的时候都具有对应于该行字段名称的属性。因此,行值可以使用标准的object->property符号来访问。
如果你属于那种喜欢鱼与熊掌兼得的类型的人,你大概会喜欢mysql_fetch_array()函数(该函数返回一个关联数组和数值索引数组)该函数是mysql_fetch_row() 及mysql_fetch_assoc()函数的结合。
请到下列网址阅读相关信息:http://www.php.net/manual/en/function.mysql-fetch-array.php。
ext/mysqli扩展
如果你正在使用PHP 5,那么你可以使用新的提供了一系列新特征的ext/mysqli扩展来做同样的事。该扩展可以两种方式来使用:过程式的(使用函数)和面向对象的(使用类和属性)。考虑下一个脚本,该脚本以过程式的方式来使用ext/mysqli。
<html> <head> <basefont face="Arial"> </head> <body> <?php // set server access variables $host = "localhost"; $user = "test"; $pass = "test"; $db = "testdb"; // open connection $connection = mysqli_connect($host, $user, $pass, $db) or die ("Unable to connect!"); // create query $query = "SELECT * FROM symbols"; // execute query $result = mysqli_query($connection, $query) or die ("Error in query: $query. ".mysqli_error()); // see if any rows were returned if (mysqli_num_rows($result) > 0) { // yes // print them one after another echo "<table cellpadding=10 border=1>"; while($row = mysqli_fetch_row($result)) { echo "<tr>"; echo "<td>".$row[0]."</td>"; echo "<td>".$row[1]."</td>"; echo "<td>".$row[2]."</td>"; echo "</tr>"; } echo "</table>"; } else { // no // print status message echo "No rows found!"; } // free result set memory mysqli_free_result($result); // close connection mysqli_close($connection); ?> </body> </html>
就像你可以看到的那样,这个看起来和为ext/mysql编写的代码十分相似。唯一真正的不同(至少对肉眼来说)就是函数名字现在以mysqli_*而不是mysql_*作为开头这一事实。当然,在也有很多的不同:ext/mysqli比常规的ext/mysql更快、更安全和更强大,而且也包含了对prepared语句、结果集、多个并发查询、事务以及大量其他酷的技术的支持。
你也可以以面向对象的方式来使用ext/mysqli,在这里,每个任务(连接、查询、数据获取)实际上都是mysqli()对象的方法:
<html> <head> <basefont face="Arial"> </head> <body> <?php // set server access variables $host = "localhost"; $user = "test"; $pass = "test"; $db = "testdb"; // create mysqli object // open connection $mysqli = new mysqli($host, $user, $pass, $db); // check for connection errors if (mysqli_connect_errno()) { die("Unable to connect!"); } // create query $query = "SELECT * FROM symbols"; // execute query if ($result = $mysqli->query($query)) { // see if any rows were returned if ($result->num_rows > 0) { // yes // print them one after another echo "<table cellpadding=10 border=1>"; while($row = $result->fetch_array()) { echo "<tr>"; echo "<td>".$row[0]."</td>"; echo "<td>".$row[1]."</td>"; echo "<td>".$row[2]."</td>"; echo "</tr>"; } echo "</table>"; } else { // no // print status message echo "No rows found!"; } // free result set memory $result->close(); } else { // print error message echo "Error in query: $query. ".$mysqli->error; } // close connection $mysqli->close(); ?> </body> </html>
这里,new关键字用于实例化类mysqli的一个对象,而且传递给对象构造器连接信息(包括数据库名称)。然后,存储于变量$mysqli中的所得对象展现执行查询、获取和处理行以及处理错误的任务的方法和属性。
如果你仔细查看上述两个脚本,那么你将会注意到函数和方法名称以及脚本结构之间的众多的相似性。然而,在两个方法中,推荐面向对象的方法,尤其是根据PHP 5中的新的对象模型。
需要记住其他几个重要的差异:
•使用ext/mysqli,你可以在传递给mysqli_connect()函数或mysqli()构造器的参数中包含数据库名称。
•当调用mysqli_query()或mysqli object's query()方法时,连接标识符是强制而不是可选的。
如何操作数据插入
因此,现在你已经知道如何执行一条SELECT查询语句来从数据库中获得结果集。然而,你也可以使用PHP的MySQL API执行哪些不返回结果集的查询语句(例如,一条INSERT或者UPDATE查询)。考虑下面的例子,该例子通过要求用户通过表单输入数据然后将数据插入到数据库中演示了上述所讲的用法。
<html> <head> <basefont face="Arial"> </head> <body> <?php if (!isset($_POST['submit'])) { // form not submitted ?> <form action="<?=$_SERVER['PHP_SELF']?>" method="post"> Country: <input type="text" name="country"> National animal: <input type="text" name="animal"> <input type="submit" name="submit"> </form> <?php } else { // form submitted // set server access variables $host = "localhost"; $user = "test"; $pass = "test"; $db = "testdb"; // get form input // check to make sure it's all there // escape input values for greater safety $country = empty($_POST['country']) ? die ("ERROR: Enter a country") : mysql_escape_string($_POST['country']); $animal = empty($_POST['animal']) ? die ("ERROR: Enter an animal") : mysql_escape_string($_POST['animal']); // open connection $connection = mysql_connect($host, $user, $pass) or die ("Unable to connect!"); // select database mysql_select_db($db) or die ("Unable to select database!"); // create query $query = "INSERT INTO symbols (country, animal) VALUES ('$country', '$animal')"; // execute query $result = mysql_query($query) or die ("Error in query: $query. ".mysql_error()); // print message with ID of inserted record echo "New record inserted with ID ".mysql_insert_id(); // close connection mysql_close($connection); } ?> </body> </html>
这里,用户首先被呈现了一个要求输入国家名称和本国动物的表单。
一旦这个表单被提交后,表单输入在内部被用于创建INSERT查询,该查询通过使用mysql_query()方法被发送到数据库。因为mysql_query()函数返回一个指示查询是否成功的布尔值,所以检查INSERT语句是否发生以及返回一条适当的消息是可能的。
在上述例子中有两个新函数。mysql_escape_string()函数对用户输入的特殊字符(比如引号)进行转义以使得它能够安全的输入到数据库中;而mysql_insert_id()返回上一条INSERT查询所产生的ID号(只有INSERT语句插入的表格包含一个AUTO_INCREMENT字段时才有用)。这两个函数也用于ext/mysqli中。
数据操作语句
明显地,你也可以用其他数据操作语句来做同样的事情。下一个例子中演示了如何结合PHP使用一条DELETE语句来选择性的删除表格中的条目。对于该变化,这次我将使用ext/mysqli:
<html> <head> <basefont face="Arial"> </head> <body> <?php // set server access variables $host = "localhost"; $user = "test"; $pass = "test"; $db = "testdb"; // create mysqli object // open connection $mysqli = new mysqli($host, $user, $pass, $db); // check for connection errors if (mysqli_connect_errno()) { die("Unable to connect!"); } // if id provided, then delete that record if (isset($_GET['id'])) { // create query to delete record $query = "DELETE FROM symbols WHERE id = ".$_GET['id']; // execute query if ($mysqli->query($query)) { // print number of affected rows echo $mysqli->affected_rows." row(s) affected"; } else { // print error message echo "Error in query: $query. ".$mysqli->error; } } // query to get records $query = "SELECT * FROM symbols"; // execute query if ($result = $mysqli->query($query)) { // see if any rows were returned if ($result->num_rows > 0) { // yes // print them one after another echo "<table cellpadding=10 border=1>"; while($row = $result->fetch_array()) { echo "<tr>"; echo "<td>".$row[0]."</td>"; echo "<td>".$row[1]."</td>"; echo "<td>".$row[2]."</td>"; echo "<td><a href=".$_SERVER['PHP_SELF']."?id=".$row[0].">Delete</a></td>"; echo "</tr>"; } } // free result set memory $result->close(); } else { // print error message echo "Error in query: $query. ".$mysqli->error; } // close connection $mysqli->close(); ?> </body> </html>
下面是程序结果:

请注意这里mysqli对象的affected_rows属性的我的用法(其返回受最后一个操作影响的总行数)。其也用于ext/mysql中,就像函数mysql_affected_rows()那样。
数据管理函数
PHP提供了一系列函数,该等函数经设计用来告诉你你想知道的关于MySQL客户端和服务器的一切事情(比如,他们的版本号、可用数据库的总数、每个数据库中的表格数目、正在运行的进程数等等你命名的,可能都在那里)。下面是一个使用这些函数给你一幅关于MySQL关系数据库管理系统内部正在发生的事情的画面的例子。
<html> <head> <basefont face="Arial"> </head> <body> <?php // set server access variables $host = "localhost"; $user = "root"; $pass = "guessme"; $db = "testdb"; // open connection $connection = mysql_connect($host, $user, $pass) or die ("Unable to connect!"); // get database list $query = "SHOW DATABASES"; $result = mysql_query($query) or die ("Error in query: $query. ".mysql_error()); echo "<ul>"; while ($row = mysql_fetch_array($result)) { echo "<li>".$row[0]; // for each database, get table list and print $query2 = "SHOW TABLES FROM ".$row[0]; $result2 = mysql_query($query2) or die ("Error in query: $query2. ".mysql_error()); echo "<ul>"; while ($row2 = mysql_fetch_array($result2)) { echo "<li>".$row2[0]; } echo "</ul>"; } echo "</ul>"; // get version and host information echo "Client version: ".mysql_get_client_info()."<br />"; echo "Server version: ".mysql_get_server_info()."<br />"; echo "Protocol version: ".mysql_get_proto_info()."<br />"; echo "Host: ".mysql_get_host_info()."<br />"; // get server status $status = mysql_stat(); echo $status; // close connection mysql_close($connection); ?> </body> </html>
下面是输出结果可能看上去的样子:

这个脚本的第一部分相当简单:其运行SHOW DATABASES查询来获得数据库列表,然后对列表反复执行SHOW TABLES命令来获得每个数据库内的表格列表。接着,mysql_get_*_info()函数提供了客户端版本号、MySQL版本号、用于MySQL客户和服务器端之间通信的特殊MySQL客户-服务器协议的版本号、当前主机名称以及其如何连接到MySQL服务器等信息。最后,函数mysql_stat()是PHP4.3.0中的新特征,它返回一个包含MySQL服务器状态信息(包括关于服务器正常运行时间、打开的表格、每秒查询次数以及其他统计信息等信息)的字符串。
上面就是所有的内容吗?不,在你离开这里然后开始构建酷的以数据驱动的Web站点之前还没有完全结束,你应该意识到两个MySQL扩展都提供了强大的错误跟踪函数(这可以提高开发效率)。看一下下面的例子,它在SELECT查询字符串中包含了一个蓄意的错误:
<?php // connect $connection = mysql_connect("localhost", "test", "test") or die("Invalid server or user"); mysql_select_db("testdb", $connection) or die("Invalid database"); // query $query = "SELECT FROM symbols"; // result $result = mysql_query($query,$connection); // look for errors and print if(!$result) { $error_number = mysql_errno(); $error_msg = mysql_error(); echo "MySQL error $error_number: $error_msg"; } // disconnect mysql_close($connection); ?>
下面是例子的输出:

如果在你的SQL语句中出现错误,那么mysql_errno()函数显示被MySQL返回的该错误的代码,而mysql_error()函数返回实际的错误消息。将这两个都打开,然后你会发现它们可以明显的减少你花费在修理补丁上的时间。
ext/mysqli代码树包含两个用于连接错误的额外的mysqli_connect_errno()和mysqli_connect_error()函数,该等函数只包含关于连接错误(没有查询相关)的信息。像下面例子那样使用这些函数调试你的MySQL连接中的错误:
<?php // create mysqli object // open connection $mysqli = new mysqli("localhost", "test", "test", "testdb"); // check for connection errors if (mysqli_connect_errno()) { die("Unable to connect: ".mysqli_connect_error()); } // query $query = "SELECT FROM symbols"; // execute query $result = $mysqli->query($query); // look for errors and print if(!$result) { $error_number = $mysqli->errno; $error_msg = $mysqli->error; echo "MySQL error $error_number: $error_msg"; } // disconnect $mysqli->close(); ?>
如果你想知道我为什么没有在上述脚本中为这两个函数使用对象语法,实际上,原因很简单:我不能。如果在连接服务器时发生错误,那么mysqli()对象不会被创建,因此与其相关的方法和属性将不存在。正因为如此,为了在ext/mysqli中调式连接错误,你必须总是使用过程式而不是对象符号。
上面就是我为PHP 101这个主题所做的论述。在第九章中,我将会告诉你关于PHP 5的内建的另外一种数据库管理系统,非常酷的数据库引擎。不要错过!