使用 PHP 创建数据库驱动的应用程序
第 6 课:在数据库中添加新的愿望
在本课中,将使用以下两个功能扩展应用程序功能:
要实现该功能,请编辑 editWishList.php 文件并创建新文件 editWish.php 。
当前文档是在适用于 PHP 的 NetBeans IDE 中创建 CRUD 应用程序 教程的一部分。
来自上一课的应用程序源代码
MySQL 用户:单击此处 以下载源代码,该代码反映了在完成上一课之后的项目状态。
Oracle 数据库用户:单击此处 以下载源代码,该代码反映了在完成上一课之后的项目状态。
提交新的愿望
用户可使用以下步骤提交新的愿望:
用户进行登录,切换到 editWishList.php 页,然后按 "Add Wish" 按钮。editWish.php 页打开,并显示 HTML 窗体。
用户在 HTML 窗体中输入愿望说明,可能还会输入他/她希望实现愿望的日期,然后按 "Save Changes" 按钮。
如果提交窗体而未输入愿望说明,用户将返回到窗体进行重试。如果用户提交了截止日期而没有提供说明,在重新加载窗体时,将重新显示该日期。
要为用户实现此过程,请在应用程序中添加以下功能:
用户界面组件 ,包含添加愿望的 HTML 窗体以及 editWishList.php 中将用户重定向到该窗体的按钮。
在提交不完整的窗体时重新显示截止日期 的代码。
添加用户界面组件
添加功能以添加新的愿望:
实现 "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 页。由于没有通过该窗体传输任何数据,因此,不会使用服务器请求方法。
在 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>
在 "Source Files"(源文件)文件夹中创建 editWish.php PHP 文件。
在 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 值(如果已输入)。在当前的窗体实现中,这两个字段始终为空。要保留输入的值,您需要将新愿望数据保存到数组中。该数组包含两个名为 description 和 due_date 的元素。然后,您需要更改 "Add Wish" 窗体,使其能够从数组中检索 dueDate 字段值。
注: 未输入说明时,重新加载输入窗体的代码包含在用于验证数据并将其输入到数据库的代码 中。本部分未介绍该代码。本部分中的代码仅保留 dueDate 值,以便在重新加载窗体时显示该值。
在用户提交输入窗体失败后重新显示该窗体:
在 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 页以及 description 和 due_date 元素均为空。
注: 在这两种情况下,说明均为空。唯一的区别是 dueDate 。
更新 "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.php 的 WishDB 类中添加另外两个辅助函数。
一个函数将新记录添加到 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 函数添加到 db.php 的 WishDB 类中。该函数需要一个字符串,并将日期作为输入参数。该函数返回具有数据库服务器可处理的格式的日期;如果输入字符串为空,则返回空值 。
注: 本示例中的函数使用 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'];
}
}
如果输入字符串为空,则代码返回空值。否则,将 $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" 窗体。如果数据无效的原因是没有输入说明,但输入了截止日期,则会保存截止日期并在重新加载窗体时重新显示该日期,您以前开发的 代码实现了该功能。
在顶部 <? php?> 块(属于
editWish.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。
测试添加愿望功能
运行应用程序。在 index.php 页上,填写以下字段:在 "Username" 字段中输入 "Tom",在 "Password" 字段中输入 "tomcat"。
按 "Edit My Wish List" 按钮。editWishList.php 页打开。
按 "Back to Main Page" 按钮。index.php 页打开。
以 Tom 身份登录,然后再次按 "Edit My Wish List" 按钮。editWishList.php 页打开。
按 "Add Wish" 按钮。editWish.php 页打开。填写窗体。 按 "Back to the List" 按钮。editWishList.php 页打开,但未添加输入的愿望。
再次按 "Add Wish" 按钮。editWish.php 页打开。填写截止日期并将说明保留空白。按 "Save Changes" 按钮。editWish.php 页将显示输入窗体,其中包含一条错误消息和填写的截止日期。
再次按 "Add Wish" 按钮。editWish.php 页打开。填写窗体,然后按 "Save Changes" 按钮。editWishList.php 页将显示更新的愿望列表。
完成当前课程后的应用程序源代码
MySQL 用户:单击此处 以下载源代码,该代码反映了在完成课程后的项目状态。
Oracle 数据库用户:单击此处 以下载源代码,该代码反映了在完成课程后的项目状态。
后续步骤
<< 上一课 下一课 >> 返回到教程主页
要发送意见和建议、获得支持以及随时了解 NetBeans IDE PHP 开发功能的最新开发情况,请加入
users
@
php.netbeans.org
邮件列表 。
返回至 PHP 学习资源