PHP 中的 $_GET、$_POST 和 $_REQUEST 变量用于检索表单中的用户输入信息。表单是Web应用程序与用户交互的重要方式。
当处理 HTML 表单时,PHP 能自动将表单元素的值转换为 PHP 脚本可用的变量。
| 超全局变量 | 描述 | 使用场景 |
|---|---|---|
$_GET |
通过 URL 参数传递的数据 | 获取数据、搜索、分页等 |
$_POST |
通过 HTTP POST 方法传递的数据 | 提交表单、上传文件、敏感数据 |
$_REQUEST |
包含 $_GET、$_POST 和 $_COOKIE 的数据 |
不推荐使用,安全性较低 |
HTML 表单 (index.html):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
<style>
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"],
input[type="email"],
input[type="password"] {
width: 300px;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.error {
color: red;
font-size: 14px;
}
</style>
</head>
<body>
<h1>用户注册表单</h1>
<form action="process_form.php" method="post">
<div class="form-group">
<label for="fname">名字:</label>
<input type="text" id="fname" name="fname" required>
</div>
<div class="form-group">
<label for="lname">姓氏:</label>
<input type="text" id="lname" name="lname" required>
</div>
<div class="form-group">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="age">年龄:</label>
<input type="text" id="age" name="age">
</div>
<div class="form-group">
<label>性别:</label>
<input type="radio" id="male" name="gender" value="male">
<label for="male">男</label>
<input type="radio" id="female" name="gender" value="female">
<label for="female">女</label>
</div>
<div class="form-group">
<label>兴趣爱好:</label>
<input type="checkbox" id="sports" name="hobbies[]" value="sports">
<label for="sports">运动</label>
<input type="checkbox" id="reading" name="hobbies[]" value="reading">
<label for="reading">阅读</label>
<input type="checkbox" id="music" name="hobbies[]" value="music">
<label for="music">音乐</label>
</div>
<div class="form-group">
<label for="country">国家:</label>
<select id="country" name="country">
<option value="">请选择</option>
<option value="china">中国</option>
<option value="usa">美国</option>
<option value="uk">英国</option>
</select>
</div>
<div class="form-group">
<label for="bio">个人简介:</label>
<textarea id="bio" name="bio" rows="4" cols="50"></textarea>
</div>
<input type="submit" value="提交">
<input type="reset" value="重置">
</form>
</body>
</html>
PHP 处理脚本 (process_form.php):
<?php
// 检查表单是否已提交
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// 获取表单数据
$firstName = $_POST['fname'] ?? '';
$lastName = $_POST['lname'] ?? '';
$email = $_POST['email'] ?? '';
$age = $_POST['age'] ?? '';
$gender = $_POST['gender'] ?? '';
$hobbies = $_POST['hobbies'] ?? [];
$country = $_POST['country'] ?? '';
$bio = $_POST['bio'] ?? '';
// 显示结果
echo "<!DOCTYPE html>";
echo "<html lang='zh-CN'>";
echo "<head><title>表单处理结果</title></head>";
echo "<body>";
echo "<h1>表单提交成功!</h1>";
echo "<h2>您的信息:</h2>";
echo "<p><strong>姓名:</strong> " . htmlspecialchars($firstName) . " " . htmlspecialchars($lastName) . "</p>";
echo "<p><strong>邮箱:</strong> " . htmlspecialchars($email) . "</p>";
if (!empty($age)) {
echo "<p><strong>年龄:</strong> " . htmlspecialchars($age) . "</p>";
}
if (!empty($gender)) {
echo "<p><strong>性别:</strong> " . htmlspecialchars($gender) . "</p>";
}
if (!empty($hobbies)) {
echo "<p><strong>兴趣爱好:</strong> " . implode(', ', array_map('htmlspecialchars', $hobbies)) . "</p>";
}
if (!empty($country)) {
echo "<p><strong>国家:</strong> " . htmlspecialchars($country) . "</p>";
}
if (!empty($bio)) {
echo "<p><strong>个人简介:</strong> <br>" . nl2br(htmlspecialchars($bio)) . "</p>";
}
echo "<a href='index.html'>返回表单</a>";
echo "</body></html>";
} else {
// 如果不是POST请求,重定向到表单页
header("Location: index.html");
exit;
}
?>
| 特性 | GET 方法 | POST 方法 |
|---|---|---|
| 数据位置 | URL 参数 | HTTP 请求体 |
| 数据可见性 | 可见(在URL中) | 不可见 |
| 数据长度限制 | 有限制(约2048字符) | 无限制 |
| 安全性 | 较低 | 较高 |
| 缓存 | 可缓存 | 不可缓存 |
| 使用场景 | 获取数据、搜索、分页 | 提交表单、上传文件、敏感操作 |
GET 方法示例:
<!-- 搜索表单 -->
<form action="search.php" method="get">
<input type="text" name="keyword" placeholder="输入搜索关键词">
<input type="submit" value="搜索">
</form>
<!-- 生成的URL:search.php?keyword=用户输入 -->
<?php
// search.php
if (isset($_GET['keyword'])) {
$keyword = $_GET['keyword'];
echo "搜索关键词: " . htmlspecialchars($keyword);
// 执行搜索逻辑...
}
?>
表单验证是确保数据安全和完整性的关键步骤,应该在客户端和服务器端都进行验证。
完整的表单验证示例:
<?php
// 初始化变量
$errors = [];
$firstName = $lastName = $email = $age = $gender = $bio = '';
$hobbies = [];
$country = '';
// 检查表单是否提交
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// 清理和验证数据
$firstName = clean_input($_POST['fname'] ?? '');
$lastName = clean_input($_POST['lname'] ?? '');
$email = clean_input($_POST['email'] ?? '');
$age = clean_input($_POST['age'] ?? '');
$gender = clean_input($_POST['gender'] ?? '');
$hobbies = isset($_POST['hobbies']) ? array_map('clean_input', $_POST['hobbies']) : [];
$country = clean_input($_POST['country'] ?? '');
$bio = clean_input($_POST['bio'] ?? '');
// 验证必填字段
if (empty($firstName)) {
$errors['fname'] = "名字是必填字段";
} elseif (!preg_match("/^[a-zA-Z\x{4e00}-\x{9fa5} ]+$/u", $firstName)) {
$errors['fname'] = "名字只能包含字母和中文";
}
if (empty($lastName)) {
$errors['lname'] = "姓氏是必填字段";
} elseif (!preg_match("/^[a-zA-Z\x{4e00}-\x{9fa5} ]+$/u", $lastName)) {
$errors['lname'] = "姓氏只能包含字母和中文";
}
// 验证邮箱
if (empty($email)) {
$errors['email'] = "邮箱是必填字段";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = "邮箱格式不正确";
}
// 验证年龄
if (!empty($age)) {
if (!is_numeric($age) || $age < 1 || $age > 150) {
$errors['age'] = "年龄必须是1-150之间的数字";
}
}
// 如果没有错误,处理数据
if (empty($errors)) {
// 这里可以保存到数据库或进行其他操作
echo "<div class='success'>表单提交成功!</div>";
// 显示提交的数据...
display_user_data($firstName, $lastName, $email, $age, $gender, $hobbies, $country, $bio);
}
}
/**
* 清理输入数据
*/
function clean_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
/**
* 显示用户数据
*/
function display_user_data($fname, $lname, $email, $age, $gender, $hobbies, $country, $bio) {
echo "<h3>提交的信息:</h3>";
echo "<p><strong>姓名:</strong> $fname $lname</p>";
echo "<p><strong>邮箱:</strong> $email</p>";
if (!empty($age)) echo "<p><strong>年龄:</strong> $age</p>";
if (!empty($gender)) echo "<p><strong>性别:</strong> $gender</p>";
if (!empty($hobbies)) echo "<p><strong>兴趣爱好:</strong> " . implode(', ', $hobbies) . "</p>";
if (!empty($country)) echo "<p><strong>国家:</strong> $country</p>";
if (!empty($bio)) echo "<p><strong>个人简介:</strong> <br>$bio</p>";
}
// 显示表单
display_form($firstName, $lastName, $email, $age, $gender, $hobbies, $country, $bio, $errors);
/**
* 显示表单
*/
function display_form($fname, $lname, $email, $age, $gender, $hobbies, $country, $bio, $errors) {
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>表单验证示例</title>
<style>
.error { color: red; font-size: 14px; }
.success { color: green; font-size: 16px; padding: 10px; background: #f0fff0; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; }
input[type="text"], input[type="email"], select, textarea {
width: 300px; padding: 8px; border: 1px solid #ddd; border-radius: 4px;
}
</style>
</head>
<body>
<h1>用户注册表单(带验证)</h1>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<div class="form-group">
<label for="fname">名字:</label>
<input type="text" id="fname" name="fname" value="<?php echo $fname; ?>" required>
<?php if (isset($errors['fname'])) echo "<div class='error'>{$errors['fname']}</div>"; ?>
</div>
<div class="form-group">
<label for="lname">姓氏:</label>
<input type="text" id="lname" name="lname" value="<?php echo $lname; ?>" required>
<?php if (isset($errors['lname'])) echo "<div class='error'>{$errors['lname']}</div>"; ?>
</div>
<div class="form-group">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" value="<?php echo $email; ?>" required>
<?php if (isset($errors['email'])) echo "<div class='error'>{$errors['email']}</div>"; ?>
</div>
<div class="form-group">
<label for="age">年龄:</label>
<input type="text" id="age" name="age" value="<?php echo $age; ?>">
<?php if (isset($errors['age'])) echo "<div class='error'>{$errors['age']}</div>"; ?>
</div>
<div class="form-group">
<label>性别:</label>
<input type="radio" id="male" name="gender" value="male" <?php echo ($gender == 'male') ? 'checked' : ''; ?>>
<label for="male">男</label>
<input type="radio" id="female" name="gender" value="female" <?php echo ($gender == 'female') ? 'checked' : ''; ?>>
<label for="female">女</label>
</div>
<div class="form-group">
<label>兴趣爱好:</label>
<?php
$hobbyOptions = ['sports' => '运动', 'reading' => '阅读', 'music' => '音乐'];
foreach ($hobbyOptions as $value => $label) {
$checked = in_array($value, $hobbies) ? 'checked' : '';
echo "<input type='checkbox' id='$value' name='hobbies[]' value='$value' $checked>";
echo "<label for='$value'>$label</label>";
}
?>
</div>
<div class="form-group">
<label for="country">国家:</label>
<select id="country" name="country">
<option value="">请选择</option>
<option value="china" <?php echo ($country == 'china') ? 'selected' : ''; ?>>中国</option>
<option value="usa" <?php echo ($country == 'usa') ? 'selected' : ''; ?>>美国</option>
<option value="uk" <?php echo ($country == 'uk') ? 'selected' : ''; ?>>英国</option>
</select>
</div>
<div class="form-group">
<label for="bio">个人简介:</label>
<textarea id="bio" name="bio" rows="4" cols="50"><?php echo $bio; ?></textarea>
</div>
<input type="submit" value="提交">
<input type="reset" value="重置">
</form>
</body>
</html>
<?php
}
?>
安全处理示例:
<?php
// 安全处理函数
function secure_form_processing() {
// 1. 检查请求方法
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
die("无效的请求方法");
}
// 2. 验证CSRF令牌(如果使用)
if (!validate_csrf_token()) {
die("CSRF令牌验证失败");
}
// 3. 数据过滤
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);
// 4. 数据验证
$errors = [];
if (empty($username) || strlen($username) < 3) {
$errors[] = "用户名至少3个字符";
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "邮箱格式不正确";
}
if ($age === false || $age < 1 || $age > 150) {
$errors[] = "年龄必须是1-150之间的数字";
}
// 5. 如果有错误,显示错误信息
if (!empty($errors)) {
foreach ($errors as $error) {
echo "<div class='error'>$error</div>";
}
return;
}
// 6. 安全地使用数据(例如保存到数据库)
save_to_database($username, $email, $age);
}
function validate_csrf_token() {
// CSRF令牌验证逻辑
return isset($_POST['csrf_token']) &&
$_POST['csrf_token'] === ($_SESSION['csrf_token'] ?? '');
}
function save_to_database($username, $email, $age) {
// 使用预处理语句防止SQL注入
try {
$pdo = new PDO("mysql:host=localhost;dbname=test", "username", "password");
$stmt = $pdo->prepare("INSERT INTO users (username, email, age) VALUES (?, ?, ?)");
$stmt->execute([$username, $email, $age]);
echo "数据保存成功!";
} catch (PDOException $e) {
echo "数据库错误: " . $e->getMessage();
}
}
?>
PHP 还可以处理文件上传,这是一个特殊的表单处理场景。
<!-- 文件上传表单 -->
<form action="upload.php" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="avatar">选择头像:</label>
<input type="file" id="avatar" name="avatar" accept="image/*">
</div>
<input type="submit" value="上传文件">
</form>
<?php
// upload.php - 文件上传处理
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_FILES["avatar"])) {
$uploadDir = "uploads/";
$maxFileSize = 2 * 1024 * 1024; // 2MB
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
$file = $_FILES["avatar"];
// 检查错误
if ($file["error"] !== UPLOAD_ERR_OK) {
die("文件上传错误: " . $file["error"]);
}
// 检查文件大小
if ($file["size"] > $maxFileSize) {
die("文件太大,最大允许2MB");
}
// 检查文件类型
$fileType = mime_content_type($file["tmp_name"]);
if (!in_array($fileType, $allowedTypes)) {
die("只允许上传JPEG, PNG, GIF格式的图片");
}
// 生成安全文件名
$extension = pathinfo($file["name"], PATHINFO_EXTENSION);
$safeFilename = uniqid() . '.' . $extension;
$uploadPath = $uploadDir . $safeFilename;
// 移动文件
if (move_uploaded_file($file["tmp_name"], $uploadPath)) {
echo "文件上传成功!";
echo "<br>文件名: " . htmlspecialchars($safeFilename);
} else {
echo "文件上传失败";
}
}
?>
htmlspecialchars()防止XSS攻击