第 6 课:在数据库中添加新的心愿

在本课中,将使用以下两个功能扩展应用程序:

要实现该功能,请编辑 editWishList.php 文件并创建新文件 editWish.php

突出显示第 6 课中添加的内容的流程图

当前文档是在适用于 PHP 的 NetBeans IDE 中创建 CRUD 应用程序教程的一部分。

 

来自上一课的应用程序源代码

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

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

提交新的心愿

用户可使用以下步骤提交新的心愿:

  1. 用户进行登录,切换到 editWishList.php 页,然后按 "Add Wish" 按钮。将打开 editWish.php页并显示 HTML 表单。
  2. 用户在 HTML 表单中输入心愿说明,可能还会输入他/她希望实现心愿的日期,然后按 "Save Changes" 按钮。
  3. 如果提交表单而未输入心愿说明,用户将返回到表单以进行重试。如果用户提交了截止日期而没有提供说明,在重新装入表单时,将重新显示该日期。

要为用户实现此过程,请在应用程序中添加以下功能:

添加用户界面组件

添加功能以添加新的心愿

  1. 实现 "Add Wish" 按钮。在 editWishList.php文件中,在 PHP 块下面添加以下 HTML 代码:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
        <head>
    
           <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        </head>
        <body>
            <form name="addNewWish" action="editWish.php">            
                <input type="submit" value="Add Wish"/>
            </form>
        </body>
    </html>

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

    表单包含 submit 类型的 "Add Wish" 输入字段。该字段实现 "Add Wish" 按钮。当用户单击 "Add Wish" 时,他们将重定向到 editWish.php 页。由于没有通过该表单传输任何数据,因此,不会使用服务器请求方法。

  2. 在 addNewWish 表单上面添加一个表以显示许愿者的现有心愿。代码类似于 wishlist.php

    对于 MySQL 数据库

    <table border="black">
    <tr><th>Item</th><th>Due Date</th></tr>
    <?php
    require_once("Includes/db.php");
    $wisherID = WishDB::getInstance()->get_wisher_id_by_name($_SESSION["user"]);
    $result = WishDB::getInstance()->get_wishes_by_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";
    }
    ?>
    </table>

    对于 Oracle 数据库:

    <table border="black">
        <tr><th>Item</th><th>Due Date</th></tr>
        <?php
        require_once("Includes/db.php");
        $wisherID = WishDB::getInstance()->get_wisher_id_by_name($_SESSION["user"]);
        $stid = WishDB::getInstance()->get_wishes_by_wisher_id($wisherID);
        while ($row = oci_fetch_array($stid)) {
    echo "<tr><td>" . htmlentities($row['DESCRIPTION']) . "</td>";
    echo "<td>" . htmlentities($row['DUE_DATE']) . "</td></tr>\n"; } ?> </table>
  3. 在“源文件”文件夹中创建 editWish.phpPHP 文件。
  4. editWish.php中,实现 "Add Wish" 表单。在 <? php ?> 块下面键入或粘贴以下代码:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    
    <html>
        <head>
    
           <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        </head>
        <body>
            <form name="editWish" action="editWish.php" method="POST">
    Describe your wish: <input type="text" name="wish" value="" /><br/>
    When do you want to get it? <input type="text" name="dueDate" value=""/><br/>
    <input type="submit" name="saveWish" value="Save Changes"/>
    <input type="submit" name="back" value="Back to the List"/> </form> </body> </html>

"Add Wish" 表单包含:

  • 两个空文本字段,用于输入心愿说明和截止日期。
  • 在输入字段旁边输出的文本。
  • 表示 "Save Changes" 按钮的 submit字段。
  • 表示 "Back to the List" 按钮的 submit 字段,用于返回到 editWishList.php 页。

在按 "Add Wish" 按钮后,表单将通过请求方法 POST 将输入的数据提交到同一页面,即 editWish.php

在提交失败后重新显示截止日期

如果用户在 "Add Wish" 表单中未填写说明,则会显示一条错误消息,并且用户返回到 editWish.php 页。当用户返回到 editWish.php 时,"Add Wish" 表单应显示 dueDate 值(如果已输入)。在当前的表单实现中,这两个字段始终为空。要保留输入的值,您需要将新心愿数据保存到数组中。该数组包含两个名为 descriptiondue_date 的元素。然后,您需要更改 "Add Wish" 表单,以使其从数组中检索 dueDate 字段值。

注意:未输入说明时重新装入输入表单的代码包含在验证数据并将其输入到数据库的代码中。本节未介绍该代码。本节中的代码仅保留 dueDate 值,以便在重新装入表单时显示该值。

要在用户提交输入表单失败后重新显示该表单,请执行以下操作:

  1. editWish.php的 HTML <body> 元素内,紧靠输入表单上面键入或粘贴以下代码块:
    <?php 
    if ($_SERVER["REQUEST_METHOD"] == "POST")
    $wish = array("description" => $_POST["wish"],
    "due_date" => $_POST["dueDate"]);
    else
    $wish = array("description" => "",
    "due_date" => ""); ?>

    该代码检查使用哪个请求服务器方法传输数据,并创建一个名为 $wish 的数组。如果该方法是 POST(表示在尝试保存具有空说明的心愿失败后显示输入表单),则 description 元素和 due_date 接受通过 POST 传输的值。

    如果该方法不是 POST(表示在重定向表单后第一次显示输入表单),则 editWishList.php 页以及 descriptiondue_date 元素均为空。

    注意:在这两种情况下,说明均为空。唯一的区别是 dueDate

  2. 更新 "Add Wish" 表单,以便从 $wish数组中检索其输入字段的值。将 "Add Wish" 表单中的行:
    Describe your wish: <input type="text" name="wish"  value="" /><br/>
    When do you want to get it? <input type="text" name="dueDate" value=""/><br/>
    替换为:
    Describe your wish: <input type="text" name="wish"  value="<?php echo $wish['description'];?>" /><br/>
    When do you want to get it? <input type="text" name="dueDate" value="<?php echo $wish['due_date']; ?>"/><br/>

验证许愿者的登录

editWish.php文件中,在文件顶部的 <? php ?> 块中输入以下会话处理代码:

session_start();
if (!array_key_exists("user", $_SESSION)) {
    header('Location: index.php');
    exit;
}

该代码执行以下操作:

  • 打开 $_SESSION 数组以检索数据。
  • 验证 $_SESSION 数组是否包含具有标识符 "user" 的元素。
  • 如果检查失败(表示用户未登录),则将应用程序重定向到主页 index.php 并取消 PHP 处理。

要检查会话处理是否正常工作,请从 IDE 中运行 editWish.php 文件。将打开 index.php 页,因为没有通过会话将用户传输到 editWish.page。

在数据库中插入新的心愿

在用户提交新的心愿后,应用程序需要将心愿添加到“心愿”数据库中。要实现该功能,请在应用程序中添加以下代码:

  • db.phpWishDB类中添加另外两个辅助函数。
    • 一个函数将新记录添加到 wishes 表中。
    • 另一个函数将日期转换为 MySQL 数据库服务器支持的格式。
  • editWish.php 中添加代码,以使用 WishDB 中的新辅助函数在数据库中输入新的心愿。

将 insert_wish 函数添加到 WishDB 中

该函数要求将许愿者 ID、新心愿说明和心愿截止日期作为输入参数,并在数据库的新记录中输入该数据。该函数不会返回任何值。

打开 db.php 并将 insert_wish 函数添加到 WishDB 类中:

对于 MySQL 数据库

function insert_wish($wisherID, $description, $duedate){
    $description = $this->real_escape_string($description);
if ($this->format_date_for_sql($duedate)==null){
$this->query("INSERT INTO wishes (wisher_id, description)" .
" VALUES (" . $wisherID . ", '" . $description . "')");
} else
$this->query("INSERT INTO wishes (wisher_id, description, due_date)" .
" VALUES (" . $wisherID . ", '" . $description . "', "
. $this->format_date_for_sql($duedate) . ")"); }

对于 Oracle 数据库:

function insert_wish($wisherID, $description, $duedate) {
  $query = "INSERT INTO wishes (wisher_id, description, due_date) VALUES (:wisher_id_bv, :desc_bv, to_date(:due_date_bv, 'YYYY-MM-DD'))"; 
  $stid = oci_parse($this->con, $query);
  oci_bind_by_name($stid, ':wisher_id_bv', $wisherID);
  oci_bind_by_name($stid, ':desc_bv', $description);
  oci_bind_by_name($stid, ':due_date_bv', $this->format_date_for_sql($duedate));
  oci_execute($stid);
  oci_free_statement($stid);
}

该代码调用 format_date_for_sql 函数,以将输入的截止日期转换为数据库服务器可以处理的格式。然后,执行 INSERT INTO wishes (wisher_id, description, due_date) 查询以在数据库中输入新的心愿。

将 format_date_for_sql 函数添加到 WishDB 中

format_date_for_sql 函数添加到 db.phpWishDB 类中。该函数需要一个字符串,并将日期作为输入参数。该函数返回具有数据库服务器可处理的格式的日期;如果输入字符串为空,则返回 null

注意:本示例中的函数使用 PHP date_parse 函数。该函数仅适用于英语语言的日期(如 December 25, 2010)和阿拉伯数字。专业 Web 站点应使用日期选取器。

对于 MySQL 数据库:

function format_date_for_sql($date){
if ($date == "")
return null;
else {
$dateParts = date_parse($date);
return $dateParts["year"]*10000 + $dateParts["month"]*100 + $dateParts["day"];
}
}

对于 Oracle 数据库:

function format_date_for_sql($date){
    if ($date == "")
        return null;
    else {
        $dateParts = date_parse($date);
        return $dateParts['year']*10000 + '-' + $dateParts['month']*100 + '-' + $dateParts['day'];
   }
}

如果输入字符串为空,则代码返回 NULL。否则,将 $date 作为输入参数以调用内部 date_parse 函数。date_parse 函数返回一个数组,其中包含三个名为 $dateParts["year"]$dateParts["month"]$dateParts["day"] 的元素。最终输出字符串由 $dateParts 数组元素组成。

重要说明:date_parse 函数仅识别英语日期。例如,它解析 "February 2, 2016" 而不解析 "2 Unora, 2016"。

Oracle 数据库用户注意事项:唯一的格式要求是,return $dateParts... 语句中的日期格式应与 insert_wish 查询的 to_date SQL 函数中的日期格式相匹配。

在数据库中输入新的心愿记录

现在,您已开发了辅助函数,接下来便可添加代码以验证新的心愿数据;如果数据有效,则将数据输入到数据库中。如果数据无效,代码必须重新装入 "Add Wish" 表单。如果数据无效的原因是没有输入说明,但输入了截止日期,则会保存截止日期并在重新装入表单时重新显示该日期,您以前开发的代码实现了该功能。

在 editWish.php 的顶部 <? php?> 块中,在会话处理代码下面输入以下代码:

require_once("Includes/db.php");
    $wisherID = WishDB::getInstance()->get_wisher_id_by_name($_SESSION['user']);

    $wishDescriptionIsEmpty = false;
    if ($_SERVER['REQUEST_METHOD'] == "POST"){
        if (array_key_exists("back", $_POST)) {
           header('Location: editWishList.php' ); 
           exit;
        } else
        if ($_POST['wish'] == "") {
            $wishDescriptionIsEmpty =  true;
        } 
		 else {
           WishDB::getInstance()->insert_wish($wisherID, $_POST['wish'], $_POST['dueDate']);
           header('Location: editWishList.php' );
           exit;
        }
    }
	

该代码执行以下功能:

  • 允许使用 db.php文件
  • 获取或创建 WishDB类实例
  • 通过调用 get_wisher_id_by_name函数,检索尝试添加心愿的许愿者的 ID
  • 初始化 $wishDescriptionIsEmpty标志,该标志将在以后显示错误消息时使用。
  • 检查请求方法是否为 POST,这意味着从表单中提交了数据以在 editWish.php页本身上输入心愿数据。
  • 检查 $_POST 数组是否包含具有 "back" 键的元素

如果 $_POST 数组包含具有 "back" 键的元素,则在提交表单之前按了 "Back to the List" 按钮。在这种情况下,代码将用户重定向到 editWishList.php,而不保存在字段中输入的任何数据并停止 PHP 处理。

如果 $_POST 数组包含具有 "back" 键的元素,则数据是通过按 "Save Changes" 按钮提交的。在这种情况下,代码验证是否填写了心愿说明。该代码的工作方式是,检查 $_POST 数组中具有 "wish" 键的元素是否为空;如果该键为空,则将 $wishDescriptionIsEmpty 标志更改为 true。请注意,不会在 PHP 块中执行其他代码,将重新装入 "Add Wish" 表单。

如果未按 "Back to the List" 按钮并填写了心愿说明,代码将调用 insert_wish 函数并将许愿者 ID、说明和心愿截止日期作为输入参数。然后,代码将用户重定向到 editWishList.php 页并停止 PHP 处理。

显示错误消息

如果用户尝试保存心愿,但没有输入心愿说明,则一定会显示错误消息。
在 HTML 输入表单中,在 "Describe your wish" 输入字段下面输入以下 <? php?> 块:

<?php
if ($wishDescriptionIsEmpty) echo "Please enter description<br/>";
?>

如果 $wishDescriptionIsEmpty标志为 true,则会显示错误消息。该标志是在输入表单验证期间处理的。

返回到主页 index.php

用户应该能够随时按某个按钮以返回到应用程序主页。
要实现该功能,请在 editWishList.php文件中的结束 </body> 标记前面输入以下 HTML 输入表单:

<form name="backToMainPage" action="index.php">
<input type="submit" value="Back To Main Page"/>
</form>

在按 "Back to Main Page" 按钮时,该表单将用户重定向到主页 index.php。

测试添加心愿功能

  1. 运行应用程序。在 index.php 页上,填写以下字段:在 "Username" 字段中输入 "Tom",在 "Password" 字段中输入 "tomcat"。
    用户登录以编辑心愿列表
  2. 按 "Edit My Wish List" 按钮。将打开 editWishList.php 页。
    添加了 "Add" 按钮的编辑心愿列表
  3. 按 "Back to Main Page" 按钮。将打开 index.php页。
  4. 以 Tom 身份登录,然后再次按 "Edit My Wish List" 按钮。将打开 editWishList.php页。
  5. 按 "Add Wish" 按钮。将打开 editWish.php 页。填写表单。
    填写了新心愿的表单
    按 "Back to the List" 按钮。将打开 editWishList.php页,但未添加输入的心愿。
  6. 再次按 "Add Wish" 按钮。将打开 editWish.php 页。填写截止日期并将说明保留空白。按 "Save Changes" 按钮。editWish.php页将显示输入表单,其中包含一条错误消息和填写的截止日期。
  7. 再次按 "Add Wish" 按钮。将打开 editWish.php 页。填写表单,然后按 "Save Changes" 按钮。editWishList.php 页将显示更新的心愿列表。
    将新心愿添加到心愿列表中

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

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

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

posted @ 2011-12-16 10:48  耕耘实录  阅读(235)  评论(0)    收藏  举报