第 2 课:设计应用程序——从数据库读取数据

来源:互联网 时间:1970-01-01

创建 PHP 项目

选择“文件”>“新建项目 (Ctrl-Shift-N)”。创建一个名为 "wishlist" 的新 PHP 项目。缺省情况下,在创建 PHP 项目时,它包含 index.php 索引文件。有关创建和配置 PHP 项目的信息,请参见设置 PHP 项目。

定义页面流程图

应用程序范围涵盖以下用例:

  1. 用户查看某人的心愿列表。
  2. 用户注册为新许愿者。
  3. 用户登录并创建她/他的心愿列表。
  4. 用户登录并编辑他/她的心愿列表。

要涵盖此基本功能,您需要实现以下 PHP 文件:

  1. 主页 index.php,用于登录、注册和切换到其他用户的心愿列表。
  2. wishlist.php 页,用于查看特定许愿者的心愿列表。
  3. createNewWisher.php 页,用于注册为许愿者。
  4. editWishList.php 页,用于按所有者编辑心愿列表。
  5. editWish.php 页,用于创建和编辑心愿。

现在,您已完成了预备步骤,接下来便可开始实现基本应用程序功能了。从查看许愿者的心愿列表入手。该功能不涉及任何验证并且可以轻松进行测试,因为您已在数据库中输入了测试数据。将在两个页面(index.php 和 wishlist.php)上实现该功能。

将表单添加到 index.php

index.php 文件不包含任何 PHP 代码,因此,您可以方便地删除以下块:

index.php 文件有两个用途:

  • 显示包含数据输入控件的页面。
  • 将输入的数据传输到另一个 PHP 文件,将在其中处理该数据。在本教程中,数据将传送到一个名为 wishlist.php 的文件,将在下一节中创建该文件并进行编码。

这些操作是使用 HTML 表单执行的。每个 HTML 表单包含:

  • 与页面上的控件对应的一组字段。
  • 在用户提交表单上的数据后执行的“操作”。该操作由处理数据的页面的路径表示。

将表单添加到 index.php 中:

  1. 切换到“项目”窗口,展开项目节点和“源文件”节点,然后双击 index.php 文件。将在主 IDE 编辑器区域中打开 index.php文件。该文件包含一个用于输入 HTML 和 PHP 代码的模板。

    注意:您可以忽略来自 HTML 验证器的警告。

  2. 删除 PHP 块。index.php 文件将不包含任何 PHP 代码。
  3. 如果以下元素不存在,请将该元素插入到 <head> 元素中。该元素允许表单使用国际化 UTF-8 字符。
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  4. 从“窗口”菜单中打开组件面板,也可以按 Ctrl-Shift-8 组合键进行打开。
  5. 从组件面板的“HTML 表单”部分中,将一个表单拖放到 index.php 的 <body> 部分中。
  6. 将打开“插入表单”对话框。在“操作”字段中,键入表单将数据传输到的文件的路径。在本示例中,键入 wishlist.php。(将在与 index.php 相同的位置中创建该文件。请参见创建 wishlist.php 和测试应用程序。)选择 GET 方法以传输数据。为表单指定任意名称,例如,wishList。完成后单击“确定”。

    现在,该文件如下所示:

  7. 在表单的开头和结尾标记之间,键入 "Show wish list of: " 文本。
  8. 从组件面板的“HTML 表单”部分中,将一个文本输入组件拖放到 "Show wish list of: " 文本后面的空白区域中。将打开“插入文本输入”对话框。
  9. 将输入命名为 user。选择输入类型 text。将所有其他字段保留空白,然后单击“确定”。

    现在,该文件如下所示:

  10. 在 </form> 标记上面添加一个空行。从组件面板的“HTML 表单”部分中,将一个按钮组件拖放到该空行中。
  11. 将打开“插入按钮”对话框。在“标签”字段中键入 Go,然后单击“确定”。
  12. 现在,该表单类似于下面的代码,但有一点不同。在下面的代码中,<form> 标记中的 method 属性是显式的。NetBeans IDE 没有在表单中添加 method 属性,因为 GET 是该属性的缺省值。不过,如果 method属性是显式的,您可以更容易理解代码。
    <form action="wishlist.php" method="GET" name="wishList">
    Show wish list of: <input type="text" name="user" value=""/>
    <input type="submit" value="Go" />
    </form>

请注意以下表单元素:

  • 起始 <form> 标记包含 action 属性。action 属性指定表单将数据传输到的文件。在本示例中,该文件命名为 wishlist.php,并位于与 index.php 相同的文件夹中。(将在创建 wishlist.php 和测试应用程序部分中创建该文件。)
  • 起始 <form> 标记还包含传输数据时应用的方法 (GET)。PHP 使用 $_GET$_POST 数组存储该表单传送的值,具体取决于 method 属性值。在本示例中,PHP 使用 $_GET
  • text 输入组件。该组件是一个文本字段,用于输入某人要查看其心愿列表的用户的名字。该文本字段的起始值是一个空字符串。该字段的名称是 user。在创建数组以存储该字段的值时,PHP 将使用该字段的名称。在本示例中,存储该字段值的数组是 $_GET["user"]
  • 具有 "Go" 值的 submit 输入组件。"submit" 类型表示,输入字段作为按钮显示在页面上。在只影响该控件时,将传输值字段的数据。

创建 wishlist.php 和测试应用程序

在将表单添加到 index.php 部分中,您创建了一个表单,用户可以在其中提交用户要查看其心愿列表的人员的名字。该名字将传送到 wishlist.php 页。不过,此页面并不存在。如果运行 index.php,在提交名字时,将会出现“404:找不到文件”错误。在本节中,将创建 wishlist.php,然后测试应用程序。

创建 wishlist.php 和测试应用程序:

  1. 在创建的 "wishlist" 项目中,在“源文件”节点上单击鼠标右键,然后从上下文菜单中选择“新建”>“PHP Web 页”。将打开“新建 PHP Web 页”向导。
  2. 在“文件名称”字段中键入 wishlist,然后按“完成”。
  3. 在“源”节点上单击鼠标右键,然后从上下文菜单中选择“运行项目”;或者,如果已将项目设置为主项目,请单击工具栏上的“运行主项目”图标
  4. 在 Show wish list of: 编辑框中,输入 Tom,然后单击 "Go"。将显示一个具有以下 URL 的空白页:http://localhost:90/Lesson2/wishlist.php?user=tom。该 URL 表示主页正常工作。

建立连接和获取许愿者 ID

在本节中,先在 wishlist.php 中添加代码以创建数据库连接。然后,添加代码以检索在 index.php 表单中键入其名字的许愿者的 ID 号。

  1. 双击 wishlist.php 文件。打开的模板与 index.php 不同。该文件以 <html></html> 和 <body></body> 标记开头和结尾,因为该文件还包含 HTML 代码。
    <html> <body> <?php /* * To change this template, choose Tools | Templates * and open the template in the editor. */ ?> </body></html>
  2. 要显示标题,请在紧靠起始 <body> 标记后面以及生成的 <?php 标记前面输入以下代码块:
     Wish List of <?php echo $_GET["user"]."<br/>";?>

    现在,代码如下所示:

    <html><body>Wish List of <?php echo $_GET["user"]."<br/>";?>
    <?php
    /*
    * To change this template, choose Tools | Templates
    * and open the template in the editor.
    */ ?>
    </body></html>

    PHP 代码块显示通过 "user" 字段中的 GET 方法接收的数据。在 "user" 文本字段中输入心愿列表所有者 Tom 的名字时,将从 index.php 中传输该数据。重复测试 index.php 中的步骤,以查看 wishlist.php 是否正常工作。

  3. 在模板 PHP 块中删除注释部分。在该位置中,键入或粘贴以下代码。该代码打开数据库连接。

    对于 MySQL 数据库:

    $con = mysqli_connect("localhost", "phpuser", "phpuserpw");
    if (!$con) {
    exit('Connect Error (' . mysqli_connect_errno() . ') '
    . mysqli_connect_error());
    }
    //set the default client character set
    mysqli_set_charset($con, 'utf-8');

    对于 Oracle 数据库:

    $con = oci_connect("phpuser", "phpuserpw", "localhost/XE", "AL32UTF8");if (!$con) { $m = oci_error(); exit('Connect Error ' . $m['message']);}

    该代码尝试打开数据库连接;如果失败,则会显示一条错误消息。

    Oracle 数据库用户注意事项:您可能需要在 oci_connect 命令中修改数据库连接。标准语法为 "hostname/service name"。按照该语法,此代码片段中的 Oracle XE 数据库连接是 "localhost/XE"。

    注意:您可以使用 NetBeans IDE 的代码完成功能完成 mysqli 或 OCI8 函数。

  4. 在打开数据库连接的代码下面,在相同 PHP 块中键入或粘贴以下代码。该代码检索请求其心愿列表的许愿者的 ID。如果许愿者不在数据库中,代码将终止/退出该进程,然后显示一条错误消息。

    对于 MySQL 数据库:

    mysqli_select_db($con, "wishlist");
    $user = mysqli_real_escape_string($con, $_GET["user"]);
    $wisher = mysqli_query($con, "SELECT id FROM wishers WHERE name='" . $user . "'");
    if (mysqli_num_rows($wisher) < 1) { exit("The person " . $_GET["user"] . " is not found. Please check the spelling and try again");}
    $row = mysqli_fetch_row($wisher);
    $wisherID = $row[0];
    mysqli_free_result($wisher);

    对于 Oracle 数据库:(请注意,oci8 没有等效的 mysqli_num_rows

    $query = "SELECT id FROM wishers WHERE NAME = :user_bv";$stid = oci_parse($con, $query);$user = $_GET['user'];oci_bind_by_name($stid, ':user_bv', $user);oci_execute($stid);//Because user is a unique value I only expect one row$row = oci_fetch_array($stid, OCI_ASSOC);if (!$row) { exit("The person " . $user . " is not found. Please check the spelling and try again" );}$wisherID = $row['ID'];oci_free_statement($stid);

    将通过 $con 连接从 wishlist 数据库中选择数据。选择条件是从 index.php 中作为 "user" 接收的名字。

    SELECT SQL 语句的语法可以简述如下:

    • 在 SELECT 后面,指定要从中获取数据的字段。星号 (*) 表示所有字段。
    • 在 FROM 子句后面,指定必须从中检索数据的表的名称。
    • WHERE 子句是可选的。将在其中指定过滤条件。

    mysqli 查询返回结果对象。OCI8 返回执行的语句。在这两种情况下,将从执行的查询结果中获取一行,并提取 ID 行的值以将其存储在 $wisherID 变量中。

    最后,释放 mysqli 结果或 OCI8 语句。在实际关闭连接之前,您需要释放使用该连接的所有资源。否则,PHP 的内部引用计数系统将基本 DB 连接保持打开,即使在 mysqli_close()oci_close() 调用后无法使用 $con

    安全注意事项:对于 MySQL,将转义 $_GET["user"] 参数以防止 SQL 注入攻击。请参见有关 SQL 注入的维基百科和 mysql_real_escape_string 文档。虽然在本教程的上下文中,您不会遇到有害 SQL 注入的风险,但最佳做法是转义存在此类攻击风险的 MySQL 查询中的字符串。OCI8 可通过绑定变量来避免该问题(请参见 PHP Oracle 常见问题解答,搜索“绑定变量”和“注入”)。

此 PHP 块现已完成。如果使用的是 MySQL 数据库,wishlist.php 文件现在如下所示:

Wish List of <?php echo $_GET["user"] . "<br/>"; ?>
<?php
$con = mysqli_connect("localhost", "phpuser", "phpuserpw"); if (!$con) { exit('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error()); }
//set the default client character set mysqli_set_charset($con, 'utf-8'); mysqli_select_db($con, "wishlist"); $user = mysqli_real_escape_string($con, $_GET["user"]); $wisher = mysqli_query($con, "SELECT id FROM wishers WHERE name='" . $user . "'"); if (mysqli_num_rows($wisher) < 1) { exit("The person " . $_GET["user"] . " is not found. Please check the spelling and try again"); } $row = mysqli_fetch_row($wisher); $wisherID = $row[0]; mysqli_free_result($wisher); ?>

如果使用的是 Oracle 数据库,则 wishlist.php 文件现在如下所示:

Wish List of <?php echo $_GET["user"] . "<br/>"; ?> <?php $con = oci_connect("phpuser", "phpuserpw", "localhost/XE", "AL32UTF8"); if (!$con) { $m = oci_error(); exit('Connect Error ' . $m['message']; exit; } $query = "SELECT id FROM wishers WHERE name = :user_bv"; $stid = oci_parse($con, $query); $user = $_GET["user"]; oci_bind_by_name($stid, ':user_bv', $user); oci_execute($stid);
//Because user is a unique value I only expect one row $row = oci_fetch_array($stid, OCI_ASSOC); if (!$row) { exit("The person " . $user . " is not found. Please check the spelling and try again" ); } $wisherID = $row["ID"]; oci_free_statement($stid); ?>

如果测试应用程序并输入无效的用户,则会显示以下消息。

显示心愿表

在本节中,将添加代码以显示与许愿者关联的 HTML 心愿表。许愿者是由在上一节的代码中检索的 ID 标识的。

  1. 在 PHP 块下面,键入或粘贴以下 HTML 代码块。该代码打开一个表,指定其边框颜色(黑色),然后使用 "Item" 和 "Due Date" 列“绘制”表标题。
    <table border="black"> <tr> <th>Item</th> <th>Due Date</th> </tr></table>
    </table> 标记用于结束表。
  2. 在结束 </table> 标记上面,输入以下 PHP 代码块。

    对于 MySQL 数据库:

    <?php
    $result = mysqli_query($con, "SELECT description, due_date FROM wishes WHERE wisher_id=" . $wisherID);
    while ($row = mysqli_fetch_array($result)) {
    echo "<tr><td>" . htmlentities($row["description"]) . "</td>";
    echo "<td>" . htmlentities($row["due_date"]) . "</td></tr>/n";
    }
    mysqli_free_result($result);
    mysqli_close($con);
    ?>

    对于 Oracle 数据库:

    <?php
    $query = "SELECT description, due_date FROM wishes WHERE wisher_id = :id_bv";
    $stid = oci_parse($con, $query);
    oci_bind_by_name($stid, ":id_bv", $wisherID);
    oci_execute($stid);
    while ($row = oci_fetch_array($stid)) {
    echo "<tr><td>" . htmlentities($row["DESCRIPTION"]) . "</td>";
    echo "<td>" . htmlentities($row["DUE_DATE"]) . "</td></tr>/n";
    }
    oci_free_statement($stid);
    oci_close($con);
    ?>

    在代码中:

    • SELECT 查询按在步骤 4 中检索的 ID 检索指定许愿者的心愿和截止日期,然后将心愿和截止日期存储在 $result 数组中。
    • 当 $result 数组不为空时,一个循环将该数组的项目作为表行进行显示。
    • <tr></tr> 标记表单行,<td></td> 标记行中的表单单元格,/n 开始一个新行。
    • htmlentities 函数将具有等效 HTML 实体的所有字符转换为 HTML 实体。这有助于防止跨站点脚本。
    • 结尾的函数释放所有资源(mysqli 结果和 OCI8 语句)并关闭数据库连接。请注意,在实际关闭连接之前,您需要释放使用该连接的所有资源。否则,PHP 的内部引用计数系统将基本 DB 连接保持打开,即使在 oci_close()mysqli_close() 调用后无法使用连接。

    警告:确保键入的数据库字段名称与创建数据库表期间指定的名称完全相同。对于 Oracle,缺省返回大写的列名。

  3. 要测试应用程序,请按照测试 index.php 部分中所述运行项目。

完成当前课程后的应用程序源代码

MySQL 用户:单击此处以下载源代码,该代码反映了在完成课程后的项目状态。

Oracle 数据库用户:单击此处以下载源代码,该代码反映了在完成课程后的项目状态。


相关阅读:
Top