2025 PHP7/8 实战入门:15 天精通现代 Web 开发——第 6 课:PHP 与 Web 交互
·
第 6 课:PHP 与 Web 交互
一、学习目标
- 理解 HTTP 协议基础与 PHP 的 Web 交互原理
- 掌握表单数据的 GET/POST 提交与处理方法
- 熟练运用 PHP7 异常处理机制处理 Web 请求错误
- 学会数据过滤与安全验证,防范常见 Web 攻击
二、核心知识点
(一)HTTP 协议与 PHP 交互基础
-
HTTP 请求与响应流程
- 请求:客户端(浏览器)向服务器发送请求(如访问网页、提交表单)
- 响应:服务器处理请求后,向客户端返回结果(如 HTML 页面、JSON 数据)
- PHP 的角色:在服务器端处理请求数据,生成动态响应内容
流程示意图:
plaintext
客户端 → 发送HTTP请求(如GET /index.php) → 服务器 → PHP解析请求并处理 → 生成响应内容 → 客户端接收并显示 -
HTTP 请求方法(PHP 通过
$_SERVER['REQUEST_METHOD']获取)- GET:从服务器获取资源(如访问网页、搜索),参数附加在 URL 后(可见,有长度限制)
- POST:向服务器提交资源(如表单提交、上传文件),参数在请求体中(不可见,无长度限制)
- 其他方法:PUT(更新资源)、DELETE(删除资源)(RESTful API 常用)
示例(URL 中的 GET 参数):
<?php // 访问URL:http://localhost/user.php?id=1&name=张三 echo "请求方法:" . $_SERVER['REQUEST_METHOD'] . "<br>"; // 输出:GET echo "用户ID:" . $_GET['id'] . "<br>"; // 输出:1 echo "用户名:" . $_GET['name'] . "<br>"; // 输出:张三 ?> -
PHP 超全局变量(Web 交互核心)
$_GET:存储 GET 请求的参数(数组)$_POST:存储 POST 请求的参数(数组)$_REQUEST:合并$_GET、$_POST、$_COOKIE(不推荐,优先级不固定)$_SERVER:存储服务器和请求相关信息(如REQUEST_METHOD、PHP_SELF)$_FILES:存储上传文件的信息(后续文件上传章节讲解)
示例(
$_SERVER常用字段):<?php echo "当前脚本路径:" . $_SERVER['PHP_SELF'] . "<br>"; // 输出:/index.php echo "请求方法:" . $_SERVER['REQUEST_METHOD'] . "<br>"; // 输出:GET或POST echo "客户端IP:" . $_SERVER['REMOTE_ADDR'] . "<br>"; // 输出:客户端IP地址 echo "服务器IP:" . $_SERVER['SERVER_ADDR'] . "<br>"; // 输出:服务器IP地址 ?>
(二)表单处理实战
-
HTML 表单创建
- 表单必须包含
action(提交目标 URL)和method(请求方法) - 表单元素需设置
name属性(PHP 通过name获取值) - 常用表单元素:
input(文本、密码、单选、复选等)、select(下拉框)、textarea(文本域)
示例(用户注册表单):
html
预览
<!-- register.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>用户注册</title> </head> <body> <h1>用户注册</h1> <!-- 表单提交到register.php,使用POST方法 --> <form action="register.php" method="post"> <div> <label>用户名:</label> <input type="text" name="username" required> <!-- required表示必填 --> </div> <div> <label>密码:</label> <input type="password" name="password" required> </div> <div> <label>确认密码:</label> <input type="password" name="confirm_password" required> </div> <div> <label>邮箱:</label> <input type="email" name="email" required> </div> <div> <label>性别:</label> <input type="radio" name="gender" value="male" checked> 男 <input type="radio" name="gender" value="female"> 女 </div> <div> <label>爱好:</label> <input type="checkbox" name="hobbies[]" value="basketball"> 篮球 <input type="checkbox" name="hobbies[]" value="football"> 足球 <input type="checkbox" name="hobbies[]" value="reading"> 读书 </div> <div> <label>城市:</label> <select name="city"> <option value="">请选择</option> <option value="beijing">北京</option> <option value="shanghai">上海</option> <option value="guangzhou">广州</option> </select> </div> <div> <textarea name="intro" placeholder="个人简介"></textarea> </div> <div> <input type="submit" name="submit" value="注册"> <input type="reset" value="重置"> </div> </form> </body> </html> - 表单必须包含
-
PHP 表单数据处理
- 接收 POST 数据:通过
$_POST['name']获取对应表单元素的值 - 复选框组:
name需设为数组形式(如hobbies[]),PHP 接收为数组 - 数据验证:检查必填项、格式合法性(如密码一致性、邮箱格式)
- 错误提示:将错误信息存储在数组中,回显到表单页面
示例(
register.php):<?php // 初始化错误信息数组 $errors = []; $user_data = []; // 判断是否为POST请求 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit'])) { // 1. 接收表单数据(并去除首尾空白) $username = trim($_POST['username'] ?? ''); $password = trim($_POST['password'] ?? ''); $confirm_password = trim($_POST['confirm_password'] ?? ''); $email = trim($_POST['email'] ?? ''); $gender = $_POST['gender'] ?? ''; $hobbies = $_POST['hobbies'] ?? []; // 复选框组,默认为空数组 $city = $_POST['city'] ?? ''; $intro = trim($_POST['intro'] ?? ''); // 2. 数据验证 // 用户名验证(长度2-10位) if (empty($username)) { $errors[] = "用户名不能为空"; } elseif (mb_strlen($username, 'UTF-8') < 2 || mb_strlen($username, 'UTF-8') > 10) { $errors[] = "用户名长度必须为2-10位"; } // 密码验证(长度6-20位,且两次输入一致) if (empty($password)) { $errors[] = "密码不能为空"; } elseif (strlen($password) < 6 || strlen($password) > 20) { $errors[] = "密码长度必须为6-20位"; } elseif ($password !== $confirm_password) { $errors[] = "两次输入的密码不一致"; } // 邮箱验证(格式合法) if (empty($email)) { $errors[] = "邮箱不能为空"; } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) { // 使用PHP内置过滤器 $errors[] = "邮箱格式不正确"; } // 城市验证(必须选择) if (empty($city)) { $errors[] = "请选择城市"; } // 3. 验证通过,处理数据(如存入数据库、创建SESSION等) if (empty($errors)) { $user_data = [ 'username' => $username, 'email' => $email, 'gender' => $gender, 'hobbies' => implode('、', $hobbies), // 数组转为字符串 'city' => $city, 'intro' => $intro ]; // 这里仅模拟成功,实际项目中会插入数据库 echo "<h2>注册成功!</h2>"; echo "<pre>"; print_r($user_data); echo "</pre>"; exit; // 终止脚本,避免显示表单 } } // 验证失败或首次访问,显示表单(将错误信息回显) ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>用户注册</title> <style> .error { color: red; } </style> </head> <body> <h1>用户注册</h1> <!-- 显示错误信息 --> <?php if (!empty($errors)): ?> <div class="error"> <ul> <?php foreach ($errors as $error): ?> <li><?= $error ?></li> <?php endforeach; ?> </ul> </div> <?php endif; ?> <!-- 表单(与register.html相同,略作修改以保留已填数据) --> <form action="register.php" method="post"> <div> <label>用户名:</label> <input type="text" name="username" value="<?= $user_data['username'] ?? '' ?>" required> </div> <!-- 其他表单元素类似,通过value="<?= $user_data['xxx'] ?? '' ?>"保留已填数据 --> <!-- 此处省略其余表单代码,与register.html一致 --> <div> <input type="submit" name="submit" value="注册"> <input type="reset" value="重置"> </div> </form> </body> </html> - 接收 POST 数据:通过
-
PHP7 过滤器扩展(数据验证简化)
- PHP 内置
filter扩展,提供常用数据验证和过滤功能 - 常用过滤器:
FILTER_VALIDATE_EMAIL:验证邮箱格式FILTER_VALIDATE_URL:验证 URL 格式FILTER_VALIDATE_INT:验证整数FILTER_SANITIZE_STRING:过滤 HTML 标签和特殊字符
示例:
<?php // 1. 验证邮箱(使用filter_var) $email = "zhangsan@example.com"; if (filter_var($email, FILTER_VALIDATE_EMAIL)) { echo "邮箱格式正确<br>"; } else { echo "邮箱格式错误<br>"; } // 2. 验证整数(指定范围1-100) $age = 25; $options = ["options" => ["min_range" => 1, "max_range" => 100]]; if (filter_var($age, FILTER_VALIDATE_INT, $options)) { echo "年龄格式正确<br>"; } else { echo "年龄必须为1-100之间的整数<br>"; } // 3. 过滤HTML标签(防止XSS攻击) $html = "<script>alert('攻击')</script> 我是张三"; $sanitized = filter_var($html, FILTER_SANITIZE_STRING); echo "过滤后:{$sanitized}<br>"; // 输出:alert('攻击') 我是张三(script标签被移除) ?> - PHP 内置
(三)PHP7 异常处理机制
-
异常的概念
- 异常:程序执行过程中出现的意外情况(如数据库连接失败、文件不存在)
- PHP7 + 支持通过
try-catch-finally捕获和处理异常,替代传统的错误判断(if-else)
-
异常处理语法
<?php try { // 可能抛出异常的代码 if (条件不满足) { throw new Exception("异常信息", 错误代码); // 手动抛出异常 } } catch (Exception $e) { // 捕获异常并处理 echo "捕获到异常:" . $e->getMessage() . "<br>"; echo "错误代码:" . $e->getCode() . "<br>"; echo "错误文件:" . $e->getFile() . "<br>"; echo "错误行号:" . $e->getLine() . "<br>"; } finally { // 无论是否抛出异常,都会执行(可选) echo "无论是否异常,我都会执行<br>"; } ?> -
Web 开发中的异常处理场景
- 表单数据验证失败(自定义异常)
- 数据库操作错误(如连接失败、查询错误)
- 文件读写错误(如文件不存在、权限不足)
示例(自定义表单验证异常):
<?php // 自定义异常类(继承自Exception) class FormValidationException extends Exception { // 可添加自定义方法(如获取错误列表) private $errorList; public function __construct(array $errors, $message = "表单验证失败", $code = 0, Exception $previous = null) { $this->errorList = $errors; parent::__construct($message, $code, $previous); } // 获取错误列表 public function getErrorList(): array { return $this->errorList; } } // 表单处理函数 function processForm(array $postData): array { $errors = []; $username = trim($postData['username'] ?? ''); if (empty($username)) { $errors[] = "用户名不能为空"; } elseif (mb_strlen($username) < 2) { $errors[] = "用户名长度不能少于2位"; } // 验证失败,抛出自定义异常 if (!empty($errors)) { throw new FormValidationException($errors); } // 验证通过,返回用户数据 return ['username' => $username]; } // 处理表单请求 try { if ($_SERVER['REQUEST_METHOD'] === 'POST') { $userData = processForm($_POST); echo "表单处理成功:" . $userData['username']; } } catch (FormValidationException $e) { // 捕获表单验证异常 echo "<h3>表单验证失败</h3>"; echo "<ul>"; foreach ($e->getErrorList() as $error) { echo "<li style='color: red;'>{$error}</li>"; } echo "</ul>"; } catch (Exception $e) { // 捕获其他异常(如系统错误) echo "系统错误:" . $e->getMessage(); // 实际项目中可记录日志 error_log("系统异常:" . $e->getMessage() . " " . $e->getFile() . ":" . $e->getLine()); } ?>
三、注意事项
-
表单安全问题
- XSS 攻击:提交包含 HTML/JS 代码的内容,需用
htmlspecialchars()转义输出(如echo htmlspecialchars($username)) - CSRF 攻击:跨站请求伪造,需添加 CSRF 令牌(如表单中加入随机 token,验证请求来源)
- 数据过滤:所有用户输入的数据都不可信,必须验证和过滤(如用
filter_var或自定义规则)
- XSS 攻击:提交包含 HTML/JS 代码的内容,需用
-
请求方法与参数安全
- 敏感操作(如登录、注册、支付)必须用 POST 方法(避免参数暴露在 URL 中)
- 避免使用
$_REQUEST(混合 GET/POST/COOKIE,易被篡改) - 验证
$_POST['submit']是否存在(防止直接访问处理脚本)
-
错误信息展示
- 开发环境:可显示详细错误信息(便于调试)
- 生产环境:隐藏详细错误信息(避免泄露系统信息),仅显示友好提示(如 “系统繁忙,请稍后再试”)
- 错误日志:生产环境将错误信息记录到日志文件(通过
error_log()函数)
四、实战练习
-
创建
day6文件夹,新建login.php和check_login.php文件:login.php:创建登录表单(包含用户名、密码输入框,提交按钮),支持显示错误提示check_login.php:处理登录请求,实现以下功能:- 验证请求方法为 POST,否则跳转回登录页
- 验证用户名和密码不为空,用户名长度 2-10 位,密码长度 6-20 位
- 模拟验证逻辑:用户名 “admin” 且密码 “123456” 为合法(实际项目中需查询数据库)
- 使用 PHP7 异常处理机制,自定义
LoginException处理登录错误(如用户名不存在、密码错误) - 登录成功则显示 “欢迎,[用户名]!”,失败则返回登录页并显示错误信息
-
新建
search.php文件:- 实现一个简单的搜索功能,支持 GET 请求传递搜索关键词(参数名
keyword) - 功能需求:
- 若未传递
keyword,显示搜索表单(输入框 + 搜索按钮) - 若传递
keyword,验证关键词长度 1-50 位,否则提示 “搜索关键词长度无效” - 模拟搜索结果:返回包含关键词的 “文章列表”(数组形式,至少 3 条模拟数据)
- 对搜索结果中的关键词进行标红处理(使用
str_replace或正则表达式) - 防范 XSS 攻击:对关键词和搜索结果进行
htmlspecialchars()转义输出
- 若未传递
- 实现一个简单的搜索功能,支持 GET 请求传递搜索关键词(参数名
更多推荐
所有评论(0)