65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 PHP 处理表单

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2018年9月8日

CPOL

22分钟阅读

viewsIcon

28931

学习在 PHP 中处理表单

引言

当今大多数网站(如果不是全部)都必须以某种方式与其用户互动。用户的互动催生了动态网页,其内容根据用户是谁(凭据)、用户是什么(角色)以及用户请求什么(功能)而变化。与内容几乎不变,因此可以在设计时制作的静态网页不同,动态网页的内容由用户互动驱动,因此只能在运行时使用服务器端脚本组合起来。

最常见的用户与动态网站的互动之一是用户通过浏览器中的网页表单向服务器发送数据。从开发人员的角度来看,表单处理的整个过程可以分为两部分——前端和后端。

  1. 在前端,浏览器显示一个精心制作的 HTML 网页表单,其中包含一个或多个表单控件——文本字段、文本区域、下拉列表、复选框、单选按钮、重置按钮、提交按钮等——用户可以在其中输入数据并提交到后端的服务器端脚本。但是,在任何数据发送到后端之前,它们必须通过前端由 HTML 表单验证和/或 JavaScript 进行的必要客户端验证。
  2. 在后端,接收服务器端脚本必须首先根据应用程序的业务规则过滤(即清理和/或验证)所有传入的表单数据,然后才能接受数据进行进一步处理。要了解 PHP 中的过滤,请参加我的另一堂关于《PHP 过滤器》的课程。

在本教程中,您将踏上动手学习之旅,设计并实现服务器端解决方案,使用 PHP 在后端接收、过滤和处理表单数据。(在继续本教程之前,您应该具备如何在前端创建网页表单的先验知识,如果没有,请先绕道前往HTML 可怕表单。)

场景设定

在本地网络服务器的文档根目录中,创建一个名为 testsite 的目录。在该目录中,创建一个名为 form.php 的 PHP 文件,当它首次通过 URL https:///testsite/form.php 启动时,它会在浏览器中显示一个网页表单。然后,用户可以通过网页表单上的各种表单控件提供并提交数据。提交时,表单数据将回发到自身,即 form.php,用于在后端进行过滤和处理。通过 postback(网页表单回发到包含它的文件的相同 URL),当任何验证失败时,可以在原始网页表单旁边显示适当的错误消息,以方便用户重新输入数据和重新提交表单,从而避免不必要的重定向。一旦数据根据应用程序的业务规则成功清理和/或验证,form.php 将简单地显示所有表单数据。整个过程最好用流程图表示,如图 1 所示。

Figure 1: Flowchart of Form Handling on Back End

图 1:后端表单处理流程图

form.php 内的网页表单将包含九个字段(姓名密码性别居住状态关于我电子邮件网页链接爱好肖像)、一个重置按钮和一个提交按钮。为了学习目的,我们假设表 1 中所示的控制各个字段数据过滤(清理和验证)的业务规则。

表 1:清理和验证规则
字段 表单控件 清理规则 验证规则
名称 <input type="text" name="username"> 禁止所有 HTML 标签。 值是必填项。
密码 <input type="password" name="userpassword"> 无。 值是必填项,且必须是八个或更多字母数字字符。
性别 <input type="radio" name="gender"> 无。 值是必填项,且必须是 citizenprforeigner 之一。
居住状态 <select name="resstatus"> 无。 值是必填项,且必须是八个或更多字母数字字符。
关于我 <textarea name="aboutme"> 所有特殊字符必须转换为 HTML 实体。例如 < 转换为 &#60; 无。
电子邮件 <input type="text" name="useremail"> 无。 值是必填项,且必须是有效的电子邮件地址。
网页链接 <input type="text" name="weblink"> 无。 值是可选的,但如果提供,则必须是有效的 URL。
爱好 <input type="checkbox" name="hobbies[]"> 无。 值是可选的,但如果提供,则必须是 CodingReadingSwimmingOthers 中的一个或多个。
肖像 <input type="file" name="portrait"> 无。 值是可选的,但如果提供,则必须是 jpgjpeg 图像类型,且不大于 200 KB。

在您出发之前,先睹为快,看看您在学习之旅结束时将收获的成果,如图 2 所示。

Figure 2: Complete Form Handling on Back End

图 2:后端完整的表单处理

初尝牛刀

首先,将以下 HTML 代码放入 form.php

<!-- Import external PHP script here -->
<!DOCTYPE html>
<html>
<head>
<title>Form Handling with PHP</title>
</head>
<body>

<header>
  <h1>Form Handling with PHP</h1>
</header>

<!-- Add form, reset, and submit buttons -->

</body>
</html>

为了清晰起见,主要的 PHP 脚本将写入一个单独的 PHP 文件,例如 include.php,并导入到 form.php 中。为此,在与 form.php 相同的目录中创建 PHP 文件 include.php。在 form.php 中标记为 <!-- Import external PHP script here --> 注释的区域,添加以下代码将 include.php 导入到 form.php

<?php include "./include.php"; ?>

您已经初尝牛刀,准备好深入了吗?

深入探究…

form.php 中标记为 <!-- Add form, reset, and submit buttons --> 注释的区域,添加以下代码来定义一个带有 Reset 按钮和 Submit 按钮的网页表单

<form method="post"">
  <!-- Add form widgets here -->
  <p>
    <input type="reset" value="Reset">
    <input type="submit" name="usersubmit" value="Submit">
  </p>
</form>

在没有 action 属性的情况下,点击 Submit 按钮时,此表单将使用 POST 方法提交到自身,即后端的 form.php。要了解浏览器和网络服务器之间的通信,请访问 HTTP 对话

从现在开始,您的旅程将变得更加激动人心,所以屏住呼吸,然后……

姓名字段

form.php 中标记为 <!-- Add form widgets here --> 注释的区域,添加以下代码来为 Name 字段定义一个文本控件,如下所示

<p>Name:<br><input type="text" name="username"></p>

表单提交时,输入到此文本控件中的值将发送到后端。服务器端脚本如何处理它?从现在开始请注意……

include.php

include.php 中,分别创建两个关联数组,名为 $messages$postback,如下所示

<?php
$messages = [
  "username" => "*"
];

$postback = [
  "username" => ""
];
?>
  • $message 存储一个以 form_widget_name=>message 对形式的消息关联数组,将在前端与其相应的表单控件一起显示,告诉用户条目是否为必需(带有 * 符号)、可选(带有空字符串),或者它是否未通过服务器端验证。目前,它只包含一个元素,即 "username" => "*",它将在 Name 文本控件旁边显示一个 * 以指示它是前端的必填字段。您稍后将编写 PHP 代码来实现这一点。
  • $postback 存储所有表单数据,以 form_widget_name=>value 对形式的关联数组,用于在服务器端因任何验证失败而将同一页面发送回用户进行重新输入时,自动填充其相应的表单控件。目前,它只包含一个元素,即 "username" => "",它将在前端的 Name 文本控件中显示一个空值。您稍后将编写 PHP 代码来实现这一点。

form.php

form.php 首次加载时,它应该在 Name 文本控件旁边显示一个 *,并带有一个空值。您已经分别在 include.php 中的 $messages$postback 数组中准备了这些初始值,现在只需使用内联 PHP 将它们输出,如下所示

  • 要在 Name 文本控件旁边显示必填字段的初始 * 符号或后续验证失败的消息,请在 <span> 元素内输出 $messages 数组中 username 键的值,如下所示
<span style="color: red"><?php echo $messages["username"]; ?><span>

使用 <span> 允许使用 CSS 对其内容进行样式设置,例如在此示例中将消息呈现为红色。

  • 要在 Name 文本控件中显示初始空值或后续回发值,请将 $postback 数组中 username 的值输出到文本控件的 value 属性中,如下所示
value="<?php echo $postback["username"]; ?>"

将它们放在一起,初始的 HTML 代码用于...

<p>Name:<br><input type="text" name="username"</p>

...变为...

<p>Name:<br><input type="text" name="username" 
value="<?php echo $postback["username"]; ?>"> 
<span style="color: red"><?php echo $messages["username"]; ?><span></p>

...现在您的 form.php 应该包含以下代码

<?php include "./include.php"; ?>
<!DOCTYPE html>
<html>
<head>
<title>Form Handling with PHP</title>
</head>
<body>

<header>
  <h1>Form Handling with PHP</h1>
</header>

<form method="post"">
  <p>Name:<br><input type="text" name="username" 
value="<?php echo $postback["username"]; ?>"> 
<span style="color: red"><?php echo $messages["username"]; ?><span></p>
  <p>
    <input type="reset" value="Reset">
    <input type="submit" name="usersubmit" value="Submit">
  </p>
</form>

</body>
</html>

在浏览器中启动 form.php,您应该能够实现如图 3 所示的动画输出

Figure 3: An Uneventful Form

图 3:平淡无奇的表单

目前,点击 Submit 按钮后,同一页面只是重新出现。是时候让服务器端脚本更努力地工作了!

增强 include.php

首先,PHP 脚本必须能够区分请求是新的还是来自表单提交的回发。您可以通过检查超全局变量 $_SERVER 的请求方法元素来确定这一点。由于 form.php 使用 POST 方法,您可以使用以下代码片段检查请求是否为回发

if($_SERVER["REQUEST_METHOD"] == "POST"){
  // Add form data processing code
}

如果条件结果为 false,它将跳过表单数据处理代码,并简单地显示一个全新的表单。如果条件结果为 true,即它是回发,那么您将需要编写代码来实现以下处理表单数据的步骤

步骤 1

根据应用程序的业务规则清理需要清理的表单数据。

第二步

验证表单数据或清理后的数据(如果需要清理)是否符合应用程序的业务规则。如果一条数据未能通过验证检查,则将 $messages 数组中与此数据对应的键的值从默认的 * 更新为适当的消息。

步骤 3

通常,如果 $messages 数组包含除默认 * 或空 string 之外的任何值,则表示某些数据未能通过其验证规则,然后它返回到 form.php 并显示相应的 $message 值及其对应的表单控件。如果 $messages 数组中的所有值都是 * 或空 string,则表示所有数据都通过了其验证规则,然后它只是输出数据。在实际应用程序中,这些数据可以保存到数据库中,或根据应用程序要求用于后续重定向到其他页面。

让我们根据表 1 中为其规定的规则,为通过 Name 文本控件提交的数据实施这些步骤。

通过 post 方法提交的所有表单数据都存储在超全局 $_POST 关联数组中,其中可以通过使用该表单控件 name 属性的值作为键来访问每个表单控件提交的数据。由于 Name 文本控件的 name 属性被赋予了 username 的值,您可以使用此代码片段访问其提交给服务器端脚本的数据

$username = $_POST["username"];

步骤 1

使用 FILTER_SANITIZE_STRING 过滤器清理 $username 的值以删除任何 HTML 标签,然后将清理后的值分配给 $postback["username"]。实现此步骤的代码如下所示

$postback["username"] = filter_var($username, FILTER_SANITIZE_STRING);

第二步

使用 PHP 函数 trim()empty() 验证 $postback["username"] 的值是否为空。如果为空,将 $messages["username"] 的值从默认的 * 更新为 Name is required 的值。实现此步骤的代码如下所示

$postback["username"] = trim($postback["username"]);
if(empty($postback["username"])){
  $messages["username"] = "Name is required";
}

步骤 3

如果 $messages 关联数组中的所有键都保留其默认值,即 * 或空 string,则表示所有数据都通过了验证。到目前为止,$messages 数组中只有一个元素,即 $messages["username"],只要 $messages* 值的计数为 1,就表示通过 Name 文本控件提交的值通过了验证,然后它返回到 form.php 并显示 $postback["username"] 的值。相反,如果 $messages* 值的计数不是 1,则表示通过 Name 文本控件提交的值未通过验证,然后它返回到 form.php 并显示初始网页表单,但在 Name 文本控件旁边添加了 Name is required 的消息。实现此步骤的代码如下所示

$array = array_count_values($messages);
if(array_key_exists("*", $array) && $array["*"] == 1){
  echo "Name: ", $postback["username"], "<br>";
  exit;
}

将您到目前为止收集到的所有片段组合在一起,您将得到一个增强的 include.php,如下所示

<?php
$messages = [
  "username" => "*"
];

$postback = [
  "username" => ""
];

if($_SERVER["REQUEST_METHOD"] === "POST"){
  
  /* Name Field */
  
  $username = $_POST["username"];
  
  // Step 1: Remove any HTML tags from $username and assign it to $postback["username"]
  $postback["username"] = filter_var($username, FILTER_SANITIZE_STRING);
  
  // Step 2: Validate that $username is not empty
  $postback["username"] = trim($postback["username"]);
  if(empty($postback["username"])){
  $messages["username"] = "Name is required";
  }
    
  /* Step 3: Determine if validations are successful */
  $array = array_count_values($messages);
  if(array_key_exists("*", $array) && $array["*"] == 1){
  echo "Name: ", $postback["username"], "<br>";
  exit;
  }
}
?>

您已完成 Name 字段的表单处理。您可以通过在浏览器中查看 form.php 来品尝您的劳动成果,或者欣赏如图 4 所示的动画片段

Figure 4: Name Field

图 4:姓名字段

在上一节中,您通过使用 Name 文本控件的练习,学习了后端表单处理的基础知识。现在您可以自信地将这些基础知识应用于设计和实现其他表单控件的后端表单处理解决方案。

密码字段

继续根据表 1 中为其规定的规则,实现 Password 密码控件的表单处理。

form.php

紧接在 form.phpName 文本控件下方,添加以下代码为 Password 字段定义一个密码控件,如下所示

<p>Password:<br><input type="password" name="userpassword" 
value="<?php echo $postback["userpassword"]; ?>"> 
<span style="color: red"><?php echo $messages["userpassword"]; ?><span></p>

include.php

include.php 中,分别向 $messages$postback 添加 "userpassword" => "*""userpassword" => "",如下所示

$messages = [
  "username" => "*",
  "userpassword" => "*"
];

$postback = [
  "username" => "",
  "userpassword" => ""
];

由于 Password 密码控件的 name 属性被赋予了 userpassword 的值,您可以使用此代码片段访问其提交给服务器端脚本的数据

$userpassword = $_POST["userpassword"];

步骤 1

根据表 1,Password 字段不需要清理。

第二步

验证 $userpassword 的值是否包含八个或更多字母数字字符。如果验证通过,将 $userpassword 的值分配给 $postback["userpassword"],否则,将 $messages["userpassword"] 的值从默认的 * 更新为 Password must be eight or more aplphanumerics。实现此步骤的代码如下所示

$options = array(
  'options' => array(
  'regexp' => '/^[A-Za-z0-9]{8,}$/'
  )
);
if(filter_var($userpassword, FILTER_VALIDATE_REGEXP, $options)){
  $postback["userpassword"] = $userpassword;
} else {
  $messages["userpassword"] = "Password must have eight or more aplphanumerics"; 
}

步骤 3

$messages* 值的计数更改为 2,并包含输出 $postback["userpassword"] 值的代码,如下所示

$array = array_count_values($messages);
if(array_key_exists("*", $array) && $array["*"] == 2){
  echo "Name: ", $postback["username"], "<br>";
  echo "Password: ", $postback["userpassword"], "<br>";
  exit;
}

将您到目前为止收集到的所有片段组合在一起,您将得到一个增强的 include.php,如下所示

<?php
$messages = [
  "username" => "*",
  "userpassword" => "*"
];

$postback = [
  "username" => "",
  "userpassword" => ""
];

if($_SERVER["REQUEST_METHOD"] === "POST"){
  
  /* Name Field */
  
  $username = $_POST["username"];
  
  // Step 1: Remove any HTML tags from $username and assign it to $postback["username"]
  $postback["username"] = filter_var($username, FILTER_SANITIZE_STRING);
  
  // Step 2: Validate that $username is not empty
  $postback["username"] = trim($postback["username"]);
  if(empty($postback["username"])){
  $messages["username"] = "Name is required";
  }

  /* Password Field */
  
  $userpassword = $_POST["userpassword"];
  
  // Step 1: Nil
  
  // Step 2: Validate that $userpassword has 8 or more alphanumerics
  $options = array(
  'options' => array(
    'regexp' => '/^[A-Za-z0-9]{8,}$/'
  )
  );
  if(filter_var($userpassword, FILTER_VALIDATE_REGEXP, $options)){
  $postback["userpassword"] = $userpassword;
  } else {
  $messages["userpassword"] = "Password must have eight or more aplphanumerics"; 
  }

  /* Step 3: Determine if validations are successful */
  $array = array_count_values($messages);
  if(array_key_exists("*", $array) && $array["*"] == 2){
  echo "Name: ", $postback["username"], "<br>";
  echo "Password: ", $postback["userpassword"], "<br>";
  exit;
  }
}
?>

您已完成 Password 字段的表单处理。您可以通过在浏览器中查看 form.php 来品尝您的劳动成果,或者欣赏如图 5 所示的动画片段

Figure 5: Password Field

图 5:密码字段

性别单选按钮组

继续根据表 1 中为其规定的规则,实现 Gender 单选按钮组的表单处理。

form.php

紧接在 form.phpPassword 密码控件下方,添加以下代码为 Gender 选项定义两个单选按钮,如下所示

<fieldset>
  <legend>Gender</legend>
  Male: <input type="radio" name="gender" value="male" 
  <?php echo $postback["gender"] === "male" ? "checked" : ""; ?>>
  Female: <input type="radio" name="gender" value="female" 
  <?php echo $postback["gender"] === "female" ? "checked" : ""; ?>>
  <span style="color: red"><?php echo $messages["gender"]; ?>
</fieldset>

include.php

include.php 中,分别向 $messages$postback 添加 "gender" => "*""gender" => "male",如下所示

$messages = [
  "username" => "*",
  "userpassword" => "*",
  "gender" => "*"
];

$postback = [
  "username" => "",
  "userpassword" => "",
  "gender" => "male"
];

$postback"gender" => "male" 元素将确保 Gender 单选按钮组的“Male”选项默认被选中。

由于 Gender 单选按钮组的 name 属性被赋予了 gender 的值,您可以使用此代码片段访问提交给服务器端脚本的选定选项

$gender = $_POST["gender"];

步骤 1

根据表 1,Gender 单选按钮组不需要清理。

第二步

验证 $gender 的值是 malefemale。如果验证通过,将 $gender 的值分配给 $postback["gender"],否则,将 $messages["gender"] 的值从默认的 * 更新为 Gender is required。实现此步骤的代码如下所示

if(in_array($gender, ["male", "female"], TRUE)){
  $postback["gender"] = $gender;  
} else {
  $messages["gender"] = "Gender is required";
}

步骤 3

$messages* 值的计数更改为 3,并包含输出 $postback["gender"] 值的代码,如下所示

$array = array_count_values($messages);
if(array_key_exists("*", $array) && $array["*"] == 3){
  echo "Name: ", $postback["username"], "<br>";
  echo "Password: ", $postback["userpassword"], "<br>";
  echo "Gender: ", $postback["gender"], "<br>";
  exit;
}

您已完成 Gender 单选按钮组的表单处理。您可以通过在浏览器中查看 form.php 来品尝您的劳动成果,或者欣赏如图 6 所示的动画片段

Figure 6: Gender Radio Group

图 6:性别单选按钮组

居住状态下拉列表

继续根据表 1 中为其规定的规则,实现 Residential Status 下拉列表的表单处理。

form.php

紧接在 form.phpGender 单选按钮组下方,添加以下代码为 Residential Status 定义一个下拉列表,如下所示

<p>
Residential Status:<br>
<select name="resstatus">
  <option value=""></option>
  <option value="citizen" <?php echo $postback["resstatus"] === "citizen" ? 
   "selected" : ""; ?>>Citizen</option>
  <option value="pr" <?php echo $postback["resstatus"] === "pr" ? 
   "selected" : ""; ?>>Permanent Resident</option>
  <option value="foreigner" <?php echo $postback["resstatus"] === "foreigner" ? 
   "selected" : ""; ?>>Foreigner</option>
</select>
<span style="color: red"><?php echo $messages["resstatus"]; ?>
</p>

include.php

include.php 中,分别向 $messages$postback 添加 "resstatus" => "*""resstatus" => "",如下所示

$messages = [
  "username" => "*",
  "userpassword" => "*",
  "gender" => "*",
  "resstatus" => "*"
];

$postback = [
  "username" => "",
  "userpassword" => "",
  "gender" => "male",
  "resstatus" => ""
];

由于 Residential Status 下拉列表的 name 属性被赋予了 resstatus 的值,您可以使用此代码片段访问提交给服务器端脚本的选定选项

$resstatus = $_POST["resstatus"];

步骤 1

根据表 1,Residential Status 下拉列表不需要清理。

第二步

验证 $resstatus 的值是否为以下之一:citizenprforeigner。如果验证通过,将 $resstatus 的值分配给 $postback["resstatus"],否则,将 $messages["resstatus"] 的值从默认的 * 更新为 Residential Status is required。实现此步骤的代码如下所示

if(in_array($resstatus, ["citizen", "pr" , "foreigner"], TRUE)){
 $postback["resstatus"] = $resstatus; 
} else {
 $messages["resstatus"] = "Residential Status is required";
}

步骤 3

$messages* 值的计数更改为 4,并包含输出 $postback["resstatus"] 值的代码,如下所示

$array = array_count_values($messages);
if(array_key_exists("*", $array) && $array["*"] == 4){
 echo "Name: ", $postback["username"], "<br>";
 echo "Password: ", $postback["userpassword"], "<br>";
 echo "Gender: ", $postback["gender"], "<br>";
 echo "Residential Status: ", $postback["resstatus"], "<br>";
 exit;
}

您已完成 Residential Status 下拉列表的表单处理。您可以通过在浏览器中查看 form.php 来品尝您的劳动成果,或者欣赏如图 7 所示的动画片段

Figure 7: Residential Status Drop-down List

图 7:居住状态下拉列表

关于我文本框

继续根据表 1 中为其规定的规则,实现 About Me 文本框的表单处理。

form.php

紧接在 form.phpResidential Status 下拉列表下方,添加以下代码为 About Me 定义一个多行文本框,如下所示

<p>About Me:<br><textarea name="aboutme" rows="10" cols="30">
<?php echo $postback["aboutme"]; ?></textarea></p>

请注意,前面控件中包含的 $message 的内联 PHP 代码不见了。由于 About Me 文本框不需要任何验证,因此无需显示 * 或任何验证失败的消息。

include.php

include.php 中,向 $postback 添加 "aboutme" => ""

由于 About Me 文本框的 name 属性被赋予了 aboutme 的值,您可以使用此代码片段访问其提交给服务器端脚本的数据

$aboutme = $_POST["aboutme"];

步骤 1

使用 FILTER_SANITIZE_FULL_SPECIAL_CHARS 过滤器清理 $aboutme 的值,将特殊字符(即 &"'<>)转换为其相应的 HTML 实体,然后将清理后的值分配给 $postback["aboutme"]。实现此步骤的代码如下所示

$postback["aboutme"] = filter_var($aboutme, FILTER_SANITIZE_FULL_SPECIAL_CHARS);

第二步

About Me 文本框不需要验证。

步骤 3

包含输出 $postback["aboutme"] 值的代码,如下所示

$array = array_count_values($messages);
if(array_key_exists("*", $array) && $array["*"] == 4){
 echo "Name: ", $postback["username"], "<br>";
 echo "Password: ", $postback["userpassword"], "<br>";
 echo "Gender: ", $postback["gender"], "<br>";
 echo "Residential Status: ", $postback["resstatus"], "<br>";
 echo "About Me: ", $postback["aboutme"], "<br>";
 exit;
}

您已完成 About Me 文本框的表单处理。您可以通过在浏览器中查看 form.php 来品尝您的劳动成果,或者欣赏如图 8 所示的动画片段

Figure 8: About Me Text Box

图 8:关于我文本框

电子邮件字段

继续根据表 1 中为其规定的规则,实现 Email 文本控件的表单处理。

form.php

紧接在 form.phpAbout Me 文本框下方,添加以下代码为 Email 字段定义一个文本控件,如下所示

<p>Email:<br><input type="text" name="useremail" 
value="<?php echo $postback["useremail"]; ?>"> 
<span style="color: red"><?php echo $messages["useremail"]; ?><span></p>

include.php

include.php 中,分别向 $messages$postback 添加 "useremail" => "*""useremail" => ""

由于 Email 文本控件的 name 属性被赋予了 useremail 的值,您可以使用此代码片段访问其提交给服务器端脚本的数据

$useremail = $_POST["useremail"];

步骤 1

根据表 1,Email 字段不需要清理。

第二步

验证 $useremail 的值是否为有效的电子邮件格式,如下所示

$useremail = trim($useremail);
if(filter_var($useremail, FILTER_VALIDATE_EMAIL)){
  $postback["useremail"] = $useremail;
} else {
  $messages["useremail"] = "Must be a valid email"; 
}

步骤 3

$messages* 值的计数更改为 5,并包含输出 $postback["useremail"] 值的代码,如下所示

$array = array_count_values($messages);
if(array_key_exists("*", $array) && $array["*"] == 5){
 echo "Name: ", $postback["username"], "<br>";
 echo "Password: ", $postback["userpassword"], "<br>";
 echo "Gender: ", $postback["gender"], "<br>";
 echo "Residential Status: ", $postback["resstatus"], "<br>";
 echo "About Me: ", $postback["aboutme"], "<br>";
 echo "Email: ", $postback["useremail"], "<br>";
 exit;
}

您已完成 Email 字段的表单处理。您可以通过在浏览器中查看 form.php 来品尝您的劳动成果,或者欣赏如图 9 所示的动画片段

Figure 9: Email Field

图 9:电子邮件字段

网页链接字段

继续根据表 1 中为其规定的规则,实现 Web Link 文本控件的表单处理。

form.php

紧接在 form.phpEmail 文本控件下方,添加以下代码为 Web Link 字段定义一个文本控件,如下所示

<p>Web Link:<br><input type="text" name="weblink" 
value="<?php echo $postback["weblink"]; ?>"> 
<span style="color: red"><?php echo $messages["weblink"]; ?><span></p>

include.php

include.php 中,分别向 $messages$postback 添加 "weblink" => ""

由于 Web Link 文本控件的 name 属性被赋予了 weblink 的值,您可以使用此代码片段访问其提交给服务器端脚本的数据

$weblink = $_POST["weblink"];

步骤 1

根据表 1,Web Link 字段不需要清理。

第二步

验证 $weblink 的值是否为有效的 URL 格式,如下所示

if(filter_var($weblink, FILTER_VALIDATE_URL)){
 $postback["weblink"] = $weblink;
} elseif (!empty($weblink)){
 $messages["weblink"] = "Must be a valid URL"; 
}

步骤 3

添加条件以检查 $weblink 的成功验证,即 empty($messages["weblink"]),然后输出 $postback["weblink"] 的值,如下所示

$array = array_count_values($messages);
if(array_key_exists("*", $array) && $array["*"] == 5 && empty($messages["weblink"])){
 echo "Name: ", $postback["username"], "<br>";
 echo "Password: ", $postback["userpassword"], "<br>";
 echo "Gender: ", $postback["gender"], "<br>";
 echo "Residential Status: ", $postback["resstatus"], "<br>";
 echo "About Me: ", $postback["aboutme"], "<br>";
 echo "Email: ", $postback["useremail"], "<br>";
 echo "Web Link: ", $postback["weblink"], "<br>";
 exit;
}

您已完成 Web Link 字段的表单处理。您可以通过在浏览器中查看 form.php 来品尝您的劳动成果,或者欣赏如图 10 所示的动画片段

Figure 10: Web Link Field

图 10:网页链接字段

爱好复选框组

继续根据表 1 中为其规定的规则,实现 Hobbies 复选框组的表单处理。

到目前为止,您一直在处理单值表单数据,然而,对于复选框组,您将期望多值表单数据,因为用户可以从复选框组中选择多个选项。要处理多值表单数据,请使用数组。

form.php

紧接在 form.phpWeb Link 文本控件下方,添加以下代码为 Hobbies 选项定义一个 checkbox 组,如下所示

<p>Hobbies:<br>
 <input type="checkbox" name="hobbies[]" value="coding" 
<?php echo in_array("coding", $postback["hobbies"], TRUE) ? "checked" : ""; ?>>Coding<br>
 <input type="checkbox" name="hobbies[]" value="reading" 
<?php echo in_array("reading", $postback["hobbies"], TRUE) ? "checked" : ""; ?>>Reading<br>
 <input type="checkbox" name="hobbies[]" value="swimming" 
<?php echo in_array("swimming", $postback["hobbies"], TRUE) ? "checked" : ""; ?>>Swimming<br>
 <input type="checkbox" name="hobbies[]" value="others" 
<?php echo in_array("others", $postback["hobbies"], TRUE) ? "checked" : ""; ?>>Others
</p>

include.php

include.php 中,向 $postback 添加 "hobbies" => []。此 $postback["hobbies"] 是一个子数组,最初将取消选中 Hobbies 复选框组的所有复选框,随后存储从 Hobbies 复选框组提交的任何值。

由于每个 Hobbies 复选框的 name 属性被赋予了 hobbies[] 的值,您可以使用此代码片段访问提交给服务器端脚本的选定选项

$hobbies = $_POST["hobbies"];

然而,如果用户在未选择任何爱好时提交表单,上述代码将导致问题。如果发生这种情况,请将 $hobbies 初始化为空数组。请使用以下代码代替

$hobbies = isset($_POST["hobbies"]) ? $_POST["hobbies"] : [];

步骤 1

根据表 1,Hobbies 复选框组不需要清理。

第二步

验证 $hobbies 的值(如果提供)必须是 codingreadingswimming 和/或 others,如下所示

if(array_sum(array_map(function($arg)
{return in_array($arg, ["coding", "reading", "swimming", "others"]);}, 
$hobbies)) == count($hobbies)){
 $postback["hobbies"] = $hobbies;
}

步骤 3

包含输出 $postback["hobbies"] 值的代码,如下所示

$array = array_count_values($messages);
if(array_key_exists("*", $array) && $array["*"] == 5 && empty($messages["weblink"])){
 echo "Name: ", $postback["username"], "<br>";
 echo "Password: ", $postback["userpassword"], "<br>";
 echo "Gender: ", $postback["gender"], "<br>";
 echo "Residential Status: ", $postback["resstatus"], "<br>";
 echo "About Me: ", $postback["aboutme"], "<br>";
 echo "Email: ", $postback["useremail"], "<br>";
 echo "Web Link: ", $postback["weblink"], "<br>";
 echo "Hobbies: ", join(', ', $postback["hobbies"]), "<br>"; 
 exit;
}

您已完成 Hobbies 复选框组的表单处理。您可以通过在浏览器中查看 form.php 来品尝您的劳动成果,或者欣赏如图 11 所示的动画片段

Figure 11: Hobbies Checkbox Group

图 11:爱好复选框组

肖像文件上传

继续根据表 1 中为其规定的规则,实现 Portrait 文件上传控件的表单处理。

form.php

紧接在 form.phpHobbies 复选框组下方,添加以下代码为 Portrait 字段定义一个文件上传控件,如下所示

<p>Portrait:<br><input type="file" name="portrait" 
value="<?php echo $postback["portrait"]; ?>"> 
<span style="color: red"><?php echo $messages["portrait"]; ?><span></p>

然而,要使 <input type="file"> 控件工作,您必须确保表单

* 使用 method="post";并且

* 在 <form> 标签中包含 enctype 属性,其值为 multipart/form-data。它指定内容不得编码,并作为流传输。

所以,将 <form> 修改为这样

<form method="post" enctype="multipart/form-data">

include.php

include.php 中,分别向 $messages$postback 添加 "portrait" => ""

由于每个 Portrait 文件上传控件的 name 属性被赋予了 portrait 的值,您可以使用此代码片段访问其提交给服务器端脚本的数据

$portrait = $_FILES["portrait"];

然而,如果用户在未选择任何文件时提交表单,上述代码将导致问题。如果发生这种情况,请将 $portrait 初始化为空数组。请使用以下代码代替

$portrait = isset($_FILES["portrait"]) ? $_FILES["portrait"] : [];

$_FILES 是一个超全局变量,它包含通过 HTTP POST 方法上传到当前脚本的任何文件的关联数组的文件相关数据。(要了解更多关于 $_FILES 的信息,请参加我的另一堂关于PHP 超全局变量的课程。)

步骤 1

根据表 1,Portrait 文件上传不需要清理。

第二步

验证上传文件(如果提供)必须是 jpgjpeg 图像类型,且不大于 200KB

if($portrait["error"] === UPLOAD_ERR_OK && 
 (!in_array(strtolower($portrait["type"]), 
 ["image/jpg", "image/jpeg"]) || $portrait["size"] > 200*1024)) {
  
  $messages["portrait"] = "File type must be of jpg or jpeg and 
                           file size must not exceed 200 KB";

} else if($portrait["error"] == UPLOAD_ERR_NO_FILE){ // No file is uploaded
  
  $postback["portrait"] = "";
  
} else { // Uploaded file passed the validation
  
  $tmp_name = $portrait["tmp_name"];
  
  $file_name = basename($portrait["name"]); 
  
  move_uploaded_file($tmp_name, $file_name);
  
  $postback["portrait"] = "<img src='$file_name' align='top' width='100px'>";
}

上传到服务器的每个文件都会临时存储,其文件名可通过 $_FILES 数组的 tmp_name 键访问,例如我们示例中的 $_FILES["portrait"]["tmp_name"]。当处理表单数据的脚本结束时,此临时文件将被删除。因此,如果您想在脚本执行之后保留文件,您必须使用 move_uploaded_file() 函数将其明确移动到永久位置,如上述步骤 2 中的脚本所示。

步骤 3

添加条件以检查 $portrait 的成功验证,即 empty($messages["portrait"]),然后输出 $postback["portrait"] 的值,如下所示:

$array = array_count_values($messages);
if(array_key_exists("*", $array) && $array["*"] == 5 && 
 empty($messages["weblink"]) && empty($messages["portrait"])){
 echo "Name: ", $postback["username"], "<br>";
 echo "Password: ", $postback["userpassword"], "<br>";
 echo "Gender: ", $postback["gender"], "<br>";
 echo "Residential Status: ", $postback["resstatus"], "<br>";
 echo "About Me: ", $postback["aboutme"], "<br>";
 echo "Email: ", $postback["useremail"], "<br>";
 echo "Web Link: ", $postback["weblink"], "<br>";
 echo "Hobbies: ", join(', ', $postback["hobbies"]), "<br>";
 echo "Portrait: ", $postback["portrait"], "<br>";
 exit;
}

您已完成 Portrait 文件上传的表单处理。您可以通过在浏览器中查看 form.php 来品尝您的劳动成果,或者欣赏如图 12 所示的动画片段

Figure 12: Portrait File Upload

图 12:肖像文件上传

任务完成

您已着陆。您已成功完成了一个动手学习之旅,设计并实现服务器端解决方案,使用 PHP 在后端接收、过滤和处理表单数据。现在您可以享受您劳动成果,就像本文开头图 2 中动画所展示的那样。

使用 PHP 处理表单》一文最初发布于Peter Leow 的博客

© . All rights reserved.