14.3 使用PHP显示MySQL数据库的数据
在PHP中建立了到MySQL的连接之后,可以执行SQL语句来查询数据库中的数据,然后通过PHP函数处理查询后的结果集,以便后续程序使用,或通过整理将这些数据显示到Web页面上。本节将介绍如何使用PHP函数完成从数据库获取数据、处理数据以及向Web页面显示数据。
说明 本节在PHP程序中使用到的数据均来自第12章介绍MySQL操作时,在MySQL自带数据库test中所建的表users。读者可以根据12章的讲述来建立该表并插入一些数据,以便理解本章的示例程序。
14.3.1 在PHP中执行SQL语句
要从数据库获取数据,首先PHP要执行一条对表操作的SQL语句,包括SELECT、INSERT、UPDATE或DELETE语句。一般情况下,在PHP中执行SELECT语句,会从表中查找出一些记录行。而执行其他语句,只会返回语句是否执行成功的信息。
通过前文的介绍,读者已经知道,在PHP中调用函数mysql_query()将会通知MySQL执行一条SQL语句。代码14-3演示了使用mysql_query()在PHP中执行一条SQL语句。
代码14-3 在PHP程序中执行SQL语句14-3.php
01 <?php 02 $host = 'localhost'; // 定义服务器 03 $user_name = 'root'; // 定义用户名 04 $password = 'admin'; // 定义密码 05 06 $conn = mysql_connect($host,$user_name,$password); // 连接MySQL 07 if(!$conn) 08 { 09 die(' 数据库连接失败:'.mysql_error()); 10 } 11 mysql_select_db('test'); // 选择数据库 12 13 $sql = 'select id,name,city from users'; 14 $result = mysql_query($sql); // 获取查询结果 15 16 if($result) 17 { 18 echo 'SQL 语句:' . $sql . '<br/> 已经成功执行!'; 19 $num = mysql_num_rows($result); // 调用函数mysql_num_row() 获得SELECT 语句查询结果的行数 20 echo '<br/> 该SQL 语句查询到<b>'.$num.'</b> 行数据'; 21 } 22 23 mysql_close($conn); 24 ?>
【代码解析】这段代码在建立了MySQL连接之后,首先在第11行调用函数mysql_select_db()选择数据库test,这个数据库是MySQL自带的一个供用户练习使用的数据库,第12章介绍的示例操作全都是在这个数据库中完成的,本章也有部分示例代码要操作这个数据库。选择完数据库之后,代码第14行调用函数mysql_query()执行一条SELECT语句,该函数返回值是一个资源标识符,用来标识SQL语句执行的结果,这个返回值并不是查询结果。当SQL语句执行成功后,在第19行调用函数mysql_num_rows()取得SELECT语句所查询到的记录数。
注意 传入mysql_num_rows()的参数是$result,它正是函数myql_query()的返回值。如果一切正常,该函数会返回如图14-5所示的结果。
通常,mysql_query()也会和mysql_error()一同使用,以便当SQL语句执行出现问题时,可以根据mysql_error()产生的信息查找问题原因。代码14-4演示了使用函数mysql_error()获得执行SQL语句发生错误时所产生的提示信息。
代码14-4 使用函数mysql_error()获取SQL语句执行错误的信息14-4.php
01 <?php 02 $host = 'localhost'; // 定义服务器 03 $user_name = 'root'; // 定义用户名 04 $password = 'admin'; // 定义密码 05 06 $conn = mysql_connect($host,$user_name,$password); // 连接MySQL 07 if(!$conn) 08 { 09 die(' 数据库连接失败:'.mysql_error()); 10 } 11 mysql_select_db('test'); // 选择数据库 12 13 $sql = 'select id,name,city,gender from users'; 14 15 // 这里使用mysql_error() 获取SQL 语句执行出错时的相关信息 16 $result = mysql_query($sql) OR die("<br/>ERROR: <b>".mysql_error()."</b><br/> <br/><br/> 产生问题 17 的SQL<br/>".$sql); 18 19 if($result) 20 { 21 echo 'SQL 语句:' . $sql . '<br/> 已经成功执行!'; 22 } 23 24 mysql_close($conn); 25 ?>
【代码解析】代码第13行定义了一个SQL语句,查询表users中某些字段的值,但字段gender不是表users中的字段,所以执行这句SQL语句是会产生错误的。第16行其实是一个逻辑表达式形式的语句,使用逻辑运算符OR来决定程序的执行。如果mysql_query()执行成功,那么程序就会继续向下执行,否则程序就会调用die(),输出一段字符串,同时终止程序的执行,这段字符串里包含了由函数mysql_error()在SQL语句执行发生错误时产生的信息。代码14-4的执行结果如图14-6所示。
图14-5 调用mysql_query()执行一条SQL语句
图14-6 使用mysql_error()获取错误信息
从图14-6可以看出,mysql_error()产生了错误信息Unknown column'gender'in'field list',说明字段gender不存在。
14.3.2 用PHP处理数据结果集
当一个SQL语句在程序中成功执行之后,可以使用mysql_fetch_array()来获取具体的查询结果,即使用该函数获取记录的字段值。代码14-5演示了调用该函数获取SELEC语句的查询结果。
代码14-5 使用函数mysql_fetch_array()获取查询结果集14-5.php
01 <?php 02 $host = 'localhost'; // 定义服务器 03 $user_name = 'root'; // 定义用户名 04 $password = 'admin'; // 定义密码 05 06 $conn = mysql_connect($host,$user_name,$password); // 连接MySQL 07 if(!$conn) 08 { 09 die(' 数据库连接失败:'.mysql_error()); 10 } 11 mysql_select_db('test'); // 选择数据库 12 13 $sql = 'select id,name,city from users'; 14 15 $result = mysql_query($sql) OR die("<br/>ERROR: <b>".mysql_error()."</b><br/> 产生 问题的SQL :".$sql); 16 17 if($num = mysql_num_rows($result)) // 判断SELECT 语句查找到的行数 18 { 19 $row = mysql_fetch_array($result); //mysql_fetch_array() 将结果集中的一行作为数组返回 20 echo '<pre>'; 21 print_r($row); // 输出由函数mysql_fetch_array() 返回的数组 22 } 23 24 mysql_close($conn); 25 ?>
【代码解析】代码第17行使用函数mysql_num_rows()的返回值来判断SELECT语句是否查找到更多的行,如果mysql_num_rows()返回值不为0,即找到数据,则调用函数mysql_fetch_array()获取结果集。执行这段代码,可以看到如图14-7所示的结果。
前文介绍函数mysql_fetch_array()时,说到该函数返回的是结果集中的一行,并将其作为关联数组或普通数组,默认该返回数组是二者兼有的。从图14-7也可以看出,mysql_fetch_array()返回的数组为每个字段值建立了两个索引,一个是以数字为索引;另一个以字段名为索引。
函数mysql_fetch_array()只能返回结果集中的一行,循环调用该函数,可以取得结果集中的所有行。代码14-6演示了调用mysql_fetch_array()取得结果集中的所有记录。
代码14-6 使用函数mysql_fetch_array()获取结果集中的所有记录14-6.php
01 <?php 02 $host = 'localhost'; // 定义服务器 03 $user_name = 'root'; // 定义用户名 04 $password = 'admin'; // 定义密码 05 06 $conn = mysql_connect($host,$user_name,$password); // 连接MySQL 07 if(!$conn) 08 { 09 die(' 数据库连接失败:'.mysql_error()); 10 } 11 mysql_select_db('test'); // 选择数据库 12 13 $sql = 'select id,name,city from users'; 14 15 $result = mysql_query($sql) OR die("<br/>ERROR: <b>".mysql_error()."</b><br/> 产生 问题的SQL :".$sql); 16 17 if($num = mysql_num_rows($result)) 18 { 19 echo '<pre>'; // 格式化输出 20 while($row = mysql_fetch_array($result,MYSQL_ASSOC)) 21 { 22 print_r($row); // 输出每行数据 23 } 24 } 25 26 mysql_close($conn); 27 ?>
【代码解析】代码20行使用while循环多次调用函数mysql_fetch_array(),每次将调用返回的数组赋给变量$row,然后在循环体内将数组变量$row输出。代码14-6的执行结果如图14-8所示。
图14-7 显示由mysql_fetch_array()返回的结果集
图14-8 使用mysql_fetch_array()获取结果集的所有记录
代码14-6中调用函数mysql_fetch_array()时指定第2个参数为MYSQL_ASSOC,因此其返回的结果集数组是以字段名为索引的关联数组。
14.3.3 向Web页面显示数据
图14-9 把数据库数据显示到Web页面
14.3.2小节已经将从程序中找到的数据显示到Web页面,但只是输出了数组结构,并不符合实际应用的需求。本小节通过把PHP代码嵌入HTML文档中,实现一个比较美观的查询结果页面,最终页面的显示效果如图14-9所示,页面代码如代码14-7所示。
实现这个页面的程序如代码14-7所示。
代码14-7 在HTML文档中嵌入PHP程序显示表中数据14-7.php
01 <?php 02 $host = 'localhost'; // 定义服务器 03 $user_name = 'root'; // 定义用户名 04 $password = 'admin'; // 定义密码 05 06 $conn = mysql_connect($host,$user_name,$password); // 连接MySQL 07 if(!$conn) 08 { 09 die(' 数据库连接失败:'.mysql_error()); 10 } 11 mysql_select_db('test'); // 选择数据库 12 13 $sql = 'select id,name,city,created_time from users'; 14 15 $result = mysql_query($sql) OR die("<br/>ERROR: <b>".mysql_error()."</b><br/> 产生 问题的SQL :".$sql); 16 ?> 17 <html> 18 <head> 19 <title>14-7.php</title> 20 </head> 21 <center> 22 23 <body> 24 <table width="75%" border="0" cellpadding="0" cellspacing="1" bgcolor="#7B7B84"> 25 <tr bgcolor="#8BBCC7"> 26 <td height="33"><div ><strong> 用户ID</strong></div></td> 27 <td><div ><strong> 用户名称</strong></div></td> 28 <td><div ><strong> 来自城市</strong></div></td> 29 <td><div ><strong> 注册时间</strong></div></td> 30 </tr> 31 32 <?php 33 if($num = mysql_num_rows($result)) 34 { 35 while($row = mysql_fetch_array($result,MYSQL_ASSOC)) 36 { 37 ?> 38 <tr bgcolor="#FFFFFF"> 39 <td height="22" ><?php echo $row['id']; ?> </td> 40 <td height="22"> <?php echo $row['name']; ?> </td> 41 <td height="22"> <?php echo $row['city']; ?> </td> 42 <td height="22"> <?php echo $row['created_time']; ?> </td> 43 </tr> 44 <?php 45 } 46 } 47 mysql_close($conn); 48 ?> 49 50 </table> 51 </body> 52 </center> 53 </html>
【代码解析】代码将PHP程序嵌入HTML文档,PHP程序的开始部分先做数据库连接等操作,然后是HTML文档部分。第35行是PHP程序while循环的开始,第39~42行,在HTML表格的单元格中嵌入PHP代码,使用echo输出每次循环获取的记录的字段值。
14.3.4 数据分页显示的原理及实现
分页显示是Web编程中最频繁处理的环节之一。所谓分页显示,就是通过程序将结果集一段一段地来显示。实现分页显示,需要两个初始参数,即每页显示多少记录和当前是第几页;再加上完整的结果集,就可以实现数据的分段显示。至于其他功能,比如上一页、下一页等均可以根据以上信息加以处理得到。
前面曾介绍如何使用LIMIT子句对查询结果做限定。比如要取得某表中的前10记录,可以使用如下SQL语句。
SELECT * FROM a_table LIMIT 0,10;
如要查找第11~20条记录,使用的SQL语句如下。
SELECT * FROM a_table LIMIT 10,10;
如要查找第21~30条记录,使用的SQL语句如下。
SELECT * FROM a_table LIMIT 20,10;
从以上SQL语句可以看出,每次取10条记录,相当于每个页面显示10条数据,而每次所要取得记录的起始位置和当前页数之间存在着这样的关系,即起始位置=(当前页数-1)×每页要显示的记录数。如果以变量$page_size表示每页显示的记录数,以变量$cur_page表示当前页数,那么上述可以用如下SQL语句模板归纳。
select * from table limit ($cur_page - 1) * $page_size, $page_size;
这样,就得到了分页情况下获取数据的SQL语句。其中$page_size可以根据实际情况指定为一个定值,实际开发中,当前页数$cur_page可以由参数传入,数据要显示的总页数可以在记录总数和每页显示的记录数之间通过计算获得。比如,如果总记录数除以每页显示的记录数后没有余数,那么总页数就是这二者之商。代码14-8在代码14-7的基础上添加了分页功能。
代码14-8 分页显示数据14-8.php
01 <?php 02 $host = 'localhost'; // 定义服务器 03 $user_name = 'root'; // 定义用户名 04 $password = 'admin'; // 定义密码 05 06 $conn = mysql_connect($host,$user_name,$password); // 连接MySQL 07 if(!$conn) 08 { 09 die(' 数据库连接失败:'.mysql_error()); 10 } 11 mysql_select_db('test'); // 选择数据库 12 13 if(isset($_GET['page'])) // 由GET 方法获得当前页数 14 { 15 $page = $_GET['page']; 16 } 17 else 18 { 19 $page = 1; 20 } 21 $page_size = 2; // 每页显示两条数据 22 23 // 获取数据总量 24 $sql = 'select * from users'; 25 $result = mysql_query($sql); 26 $total = mysql_num_rows($result); 27 28 // 开始计算总页数 29 if($total) 30 { 31 // 如果总数据量小于$page_size ,那么只有一页 32 if($total < $page_size) 33 $page_count = 1; 34 // 如果有余数,则总页数等于总记录数除以页数的结果取整再加1 35 if($total % $page_size) 36 { 37 $page_count = (int)($total/$page_size) + 1; 38 } 39 // 如果没有余数,则页数等于总数据量除以每页数的结果 40 else 41 { 42 $page_count = $total/$page_size; 43 } 44 } 45 else 46 { 47 $page_count = 0; 48 } 49 // 翻页链接 50 $turn_page = ''; 51 if($page == 1) 52 { 53 $turn_page .= ' 首页 | 上一页 |'; 54 } 55 else 56 { 57 $turn_page .= '<a href=14-8.php?page=1> 首页</a> | <a href=14-8.php?page='. ($page-1).'> 上一页 58 </a> |'; 59 } 60 if($page == $page_count || $page_count == 0) 61 { 62 $turn_page .= ' 下一页 | 尾页'; 63 } 64 else 65 { 66 $turn_page .= '<a href=14-8.php?page='.($page+1).'> 下一页 </a>|<a 67 href=14-8.php?page='.$page_count.'> 尾页 </a>'; 68 } 69 70 $sql = 'select id,name,city,created_time from users limit '. ($page-1)*$page_size .', '.$page_size; 71 $result = mysql_query($sql) OR die("<br/>ERROR: <b>".mysql_error()."</b><br/> 产生 问题的SQL :".$sql); 72 ?> 73 <html> 74 <head> 75 <title>14-8.php</title> 76 </head> 77 <center> 78 79 <body> 80 <table width="75%" border="0" cellpadding="0" cellspacing="1" bgcolor="#7B7B84"> 81 <tr bgcolor="#8BBCC7"> 82 <td height="33"><div ><strong> 用户ID</strong></div></td> 83 <td><div ><strong> 用户名称</strong></div></td> 84 <td><div ><strong> 来自城市</strong></div></td> 85 <td><div ><strong> 注册时间</strong></div></td> 86 </tr> 87 88 <?php 89 if($num = mysql_num_rows($result)) 90 { 91 while($row = mysql_fetch_array($result,MYSQL_ASSOC)) 92 { 93 ?> 94 <tr bgcolor="#FFFFFF"> 95 <td height="22" ><?php echo $row['id']; ?> </td> 96 <td height="22"> <?php echo $row['name']; ?> </td> 97 <td height="22"> <?php echo $row['city']; ?> </td> 98 <td height="22"> <?php echo $row['created_time']; ?> </td> 99 </tr> 100 <?php 101 } 102 } 103 echo $turn_page; // 将分页字符串输出 104 mysql_close($conn); 105 ?> 106 107 </table> 108 </body> 109 </center> 110 </html>
【代码解析】因为users表中的记录数不是很多,为达到分页显示的效果,代码14-8中设定每页显示的记录数为2。执行代码14-8,可以看到如图14-10所示的分页浏览数据效果。
图14-10 分页显示数据的效果