PHP 入门先练什么?用报名表串起变量、数组和校验

编程狮(w3cschool.cn) 2026-09-14 10:11:35 浏览数 (23)
反馈

PHP 入门可以从处理一份报名数据开始:读取字段,验证类型和范围,再把结果安全地显示出来。你可能已经学会变量赋值,却一接表单就不知道该相信哪个值。浏览器发来的数据不是已经整理好的业务对象,缺字段、空字符串和意外数组都可能出现。

报名数据处理先校验,再展示

本文用一个报名处理函数串起变量、关联数组和表单校验,再提供命令行自测与网页入口。示例面向 PHP 8.x,先在本地练习目录运行,不连接数据库。页面只返回确认结果,没有保存报名记录,也没有实现真实业务中的身份认证与重复提交处理。

一、先定义一份报名数据应该是什么

本例需要姓名和年龄两个字段。姓名必须是非空字符串,去掉首尾空白后最多九十个字节;年龄必须是十六到六十五之间的整数形式字符串。这里的长度按字节计算,中文字符通常占多个字节,因此它不是“最多九十个汉字”。

关联数组像带字段名称的表格行:name 对应姓名,age 对应年龄。读取不存在的键时要考虑缺省情况,但缺省值只能帮助程序继续判断,不能直接替用户做出业务决定。例如年龄缺失时,不应默认设成十八岁并接受报名。

可以从 PHP 教程 补充变量与数组基础。理解超全局变量之后,再使用 $_POST;它提供请求数据的入口,不代表数据已经可信。

二、把校验写成独立函数

新建 registration.php。先检查字段是不是字符串,再调用 trim 和过滤函数,避免请求把字段构造成数组时引发类型错误。

<?php
declare(strict_types=1);

function register(array $data): array {
    $name = $data['name'] ?? null;
    $ageText = $data['age'] ?? null;
    if (!is_string($name) || !is_string($ageText)) {
        throw new InvalidArgumentException('姓名和年龄必须是文本字段');
    }
    $name = trim($name);
    if ($name === '' || strlen($name) > 90) {
        throw new InvalidArgumentException('姓名为空或长度超出限制');
    }
    $age = filter_var($ageText, FILTER_VALIDATE_INT, [
        'options' => ['min_range' => 16, 'max_range' => 65]
    ]);
    if ($age === false) {
        throw new InvalidArgumentException('年龄必须是16到65之间的整数');
    }
    return ['name' => $name, 'age' => $age];
}

成功返回时,姓名是处理过的字符串,年龄是整数;失败时抛出明确异常。把这层逻辑独立出来,命令行和网页请求就可以复用同一套规则,不会出现两套年龄范围互相冲突。

filter_var 校验失败返回 false,因此用严格比较判断。不要用“如果没有值就默认一”这样的简写覆盖错误。另一个常见误解是先转整数再验证:某些不完整数字文本经过强制转换后会变成一个数字,原始格式错误就丢失了。

三、先在命令行验证数组输入

新建 test_registration.php,与函数文件放在同一目录。用 php test_registration.php 运行,成功时打印完成信息,失败则抛异常并使程序退出。

<?php
declare(strict_types=1);
require __DIR__ . '/registration.php';

$valid = register(['name' => ' 编程狮练习 ', 'age' => '18']);
if ($valid !== ['name' => '编程狮练习', 'age' => 18]) {
    throw new RuntimeException('正常输入结果不符');
}
$cases = [
    ['name' => '', 'age' => '18'],
    ['name' => '学员', 'age' => '15'],
    ['name' => '学员', 'age' => '66'],
    ['name' => '学员', 'age' => '18abc'],
    ['name' => ['学员'], 'age' => '18'],
    ['name' => '学员']
];
foreach ($cases as $case) {
    $rejected = false;
    try { register($case); }
    catch (InvalidArgumentException $error) { $rejected = true; }
    if (!$rejected) throw new RuntimeException('非法输入未被拒绝');
}
echo "正常输入与6组非法输入检查通过\n";

这组测试特意包括边界外年龄、含字母的数字文本和数组姓名。它验证的是用户可能提交的具体形状,不是只测试函数能否被调用一次。还应自己补十六和六十五两个端点,确认允许范围确实包含它们。

常用数组与类型判断可对照 PHP 速查手册。注意本测试不用 assert 作为唯一失败判据,而是明确抛出异常,避免运行配置导致断言未执行。

四、再接上表单,区分校验与输出转义

新建 index.php。浏览器端的 requiredminmax 是操作提示;服务端仍调用 register 进行真实校验。返回结果使用 htmlspecialchars 进入 HTML 文本位置,避免姓名被解释为标签。

<?php
declare(strict_types=1);
require __DIR__ . '/registration.php';
$message = '';
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    try {
        $record = register($_POST);
        $message = '已校验:' . $record['name'] . ',年龄 ' . $record['age'];
    } catch (InvalidArgumentException $error) {
        http_response_code(422);
        $message = $error->getMessage();
    }
}
?>
<!doctype html>
<html lang="zh-CN">
<meta charset="utf-8">
<title>编程狮 PHP 表单练习</title>
<form method="post">
  <label>姓名 <input name="name" required></label>
  <label>年龄 <input name="age" type="number" min="16" max="65" required></label>
  <button type="submit">校验资料</button>
</form>
<p><?= htmlspecialchars($message, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></p>
</html>

在练习目录启动 php -S 127.0.0.1:8080,然后访问本机八零八零端口。PHP 内置服务用于本地开发验证,不应按这个命令直接搭建公网正式站点。

校验和转义承担不同职责。校验判断数据是否符合业务;转义保证数据在特定输出位置被当作文字。姓名通过非空检查,不意味着它适合原样写入 HTML。相反,转义过的年龄字符串也不代表年龄合法。

输入或动作 应有结果 对应责任
正常姓名、十八岁 显示校验结果 业务处理
缺少年龄 返回字段错误 服务端校验
姓名含尖括号 按文字显示 HTML 输出转义
想真正保存报名 需要另写存储流程 当前示例范围外

如果下一步接数据库,应使用参数化查询,而不是把转义后的 HTML 字符串拼进 SQL。不同输出上下文有不同规则,htmlspecialchars 不是万能安全函数。异常页面也不应向用户展示数据库口令或本地文件路径。

浏览器提示不能替代服务端判断:校验决定是否接受;转义决定怎样安全地显示

总结

网页入口用 __DIR__ 定位函数文件,是为了避免启动服务器的位置改变后,相对路径指向另一处。同样,命令行测试直接传数组,能把业务校验与请求解析分开。命令行通过而网页失败时,应检查请求方法和字段名称;两边都失败时,再回到校验函数和用例本身定位。

本例对空姓名拒绝,但没有实现“真实姓名识别”。产品是否允许昵称、连字符或其他字符,应由需求决定。也不要为了过滤尖括号直接删掉所有特殊字符:输入内容是否合法与它怎样进入页面,是两套规则。业务层保留需要的信息,展示层按上下文处理,才不会一边修安全问题一边损坏正常数据。

PHP 入门的这三个知识点可以组成完整链路:变量读取字段,关联数组组织数据,校验函数把不确定输入变成明确结果。网页入口负责请求和展示,业务函数负责规则,两者分开后更容易测试。

你可以先增加一个学习方向字段,规定允许值集合,再给正常值与未知值各写一个测试。等规则稳定后再考虑数据库保存、身份认证和防重复提交。不要因为页面出现“校验成功”,就把它描述成一个已经能接受真实报名的系统。

延伸学习

  1. PHP 数组遍历实践 可作为理解数组逐项处理的补充资料。
  2. PHP 零基础入门课程 适合继续练习语法与页面交互。
  3. PHP 异常处理说明 可帮助区分业务拒绝与程序故障。

常见问题

Q:浏览器已经限制年龄,服务端为什么还检查?

因为请求可以不经过这个表单发出。浏览器限制帮助正常用户减少误填,服务端检查负责验证实际收到的数据,两者不能互相替代。

Q:strlen 为什么不是按汉字个数计数?

它统计字节长度,UTF-8 字符可能占多个字节。如果产品要求按字符数量限制,应选择相应多字节函数并确认扩展可用。

Q:转义应该在保存前还是展示前做?

通常应根据输出位置在展示时处理。存储层保留适当验证后的业务值,避免同一份数据在不同展示上下文中被重复转义或错误解释。

技术依据:PHP htmlspecialchars 文档

0 人点赞