PHP 入门教程
PHP 完整表单实例
本教程共 65 篇 · 第 25 篇 · 更新于 2026-07-24 · 约 5 分钟阅读
PHPPHP8表单实例用户注册密码哈希实战
25. PHP 完整表单实例
本节目标:通过用户注册表单的完整实战,学会把表单展示、数据验证、错误提示、安全处理整合到一个页面中。
前面两章分别讲了表单接收和验证。本章把它们串起来,做一个用户注册页面,让你看到真实项目的写法。
25.1 需求分析
注册表单需要收集以下信息:
| 字段 | 规则 |
|---|---|
| 用户名 | 必填,3-20 位字母数字下划线 |
| 邮箱 | 必填,有效邮箱格式 |
| 密码 | 必填,至少 6 位 |
| 确认密码 | 必须与密码一致 |
| 性别 | 单选,必填 |
25.2 单文件完整代码
把 HTML 表单和 PHP 处理放在同一个文件,提交后原地显示错误:
<?php
$errors = [];
$data = [
"username" => "",
"email" => "",
"gender" => "",
];
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$data["username"] = trim($_POST["username"] ?? "");
$data["email"] = trim($_POST["email"] ?? "");
$data["gender"] = $_POST["gender"] ?? "";
$password = $_POST["password"] ?? "";
$confirm = $_POST["confirm"] ?? "";
// 1. 用户名验证
if (empty($data["username"])) {
$errors["username"] = "用户名不能为空";
} elseif (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $data["username"])) {
$errors["username"] = "用户名需为 3-20 位字母、数字或下划线";
}
// 2. 邮箱验证
if (empty($data["email"])) {
$errors["email"] = "邮箱不能为空";
} elseif (!filter_var($data["email"], FILTER_VALIDATE_EMAIL)) {
$errors["email"] = "邮箱格式不正确";
}
// 3. 密码验证
if (strlen($password) < 6) {
$errors["password"] = "密码至少 6 位";
}
if ($password !== $confirm) {
$errors["confirm"] = "两次输入的密码不一致";
}
// 4. 性别验证
if (empty($data["gender"])) {
$errors["gender"] = "请选择性别";
}
// 5. 无错误则处理(如存入数据库)
if (empty($errors)) {
$hash = password_hash($password, PASSWORD_DEFAULT);
// TODO: 将 $data 和 $hash 存入数据库
echo "<p style='color:green'>注册成功!</p>";
exit;
}
}
function e(string $text): string {
return htmlspecialchars($text, ENT_QUOTES, "UTF-8");
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户注册</title>
<style>
.error { color: red; font-size: 14px; }
input[type="text"], input[type="email"], input[type="password"] { width: 200px; }
</style>
</head>
<body>
<h2>用户注册</h2>
<form method="post" action="">
<p>
用户名:<br>
<input type="text" name="username" value="<?= e($data['username']) ?>">
<span class="error"><?= $errors['username'] ?? '' ?></span>
</p>
<p>
邮箱:<br>
<input type="email" name="email" value="<?= e($data['email']) ?>">
<span class="error"><?= $errors['email'] ?? '' ?></span>
</p>
<p>
密码:<br>
<input type="password" name="password">
<span class="error"><?= $errors['password'] ?? '' ?></span>
</p>
<p>
确认密码:<br>
<input type="password" name="confirm">
<span class="error"><?= $errors['confirm'] ?? '' ?></span>
</p>
<p>
性别:<br>
<label><input type="radio" name="gender" value="male"
<?= $data['gender'] === 'male' ? 'checked' : '' ?>> 男</label>
<label><input type="radio" name="gender" value="female"
<?= $data['gender'] === 'female' ? 'checked' : '' ?>> 女</label>
<span class="error"><?= $errors['gender'] ?? '' ?></span>
</p>
<p><input type="submit" value="立即注册"></p>
</form>
</body>
</html>
Note使用
$_SERVER["REQUEST_METHOD"]判断 POST,确保首次访问页面时不执行验证逻辑。
25.3 保留用户输入的技巧
表单验证失败后,应该保留用户已填内容,只清空密码字段:
// 文本框保留值
<input type="text" name="username" value="<?= e($data['username']) ?>">
// 单选按钮保持选中
<input type="radio" name="gender" value="male" <?= $data['gender'] === 'male' ? 'checked' : '' ?>>
// 密码框不保留值(安全考虑)
<input type="password" name="password">
25.4 密码的安全存储
注册时千万不要明文存储密码。PHP 提供了 password_hash()(详见第 42 章安全基础中的密码存储章节):
<?php
$password = "user123456";
$hash = password_hash($password, PASSWORD_DEFAULT);
// $hash 存入数据库
// 验证时用 password_verify($input, $hash)
Tip
PASSWORD_DEFAULT在 PHP 8.x 默认使用 bcrypt,未来会自动升级到更安全的算法,建议始终用它。
25.5 登录表单简化版
登录只需要用户名和密码,逻辑更简单:
<?php
$err = "";
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$user = trim($_POST["user"] ?? "");
$pass = $_POST["pass"] ?? "";
// 假设从数据库取出的哈希值为 $hashFromDb
$hashFromDb = "$2y$10$..."; // 示例
if ($user === "" || $pass === "") {
$err = "请填写完整";
} elseif (!password_verify($pass, $hashFromDb)) {
$err = "用户名或密码错误";
} else {
echo "登录成功!";
exit;
}
}
?>
<form method="post">
<input type="text" name="user" placeholder="用户名"><br>
<input type="password" name="pass" placeholder="密码"><br>
<span style="color:red"><?= $err ?></span><br>
<input type="submit" value="登录">
</form>
Note登录失败时提示”用户名或密码错误”,不要具体告诉用户是哪个错了,防止被枚举。
来源:参考了 runoob「PHP 完整表单实例」、w3cschool「PHP 完整表单实例」等,改写后所得。