十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PHP后端入门:从HTML表单到MySQL存储的完整数据链路

PHP后端入门:从HTML表单到MySQL存储的完整数据链路 一套完整的 PHP 后端入门教程核心并不是把 PHP 语法从头到尾背一遍而是要把“用户在浏览器里填写的表单数据如何安全地进入 MySQL 数据库再被需要的人查询出来”这条完整链路走通。很多初学者学完 PHP 基础语法之后仍然不会写项目原因就在于语法、HTML 表单、数据库操作、校验逻辑这四块知识在课堂上是分开讲的到了实际项目里它们必须同时工作。这篇教程围绕“前端基础 MySQL PHP 表单验证 正则表达式”这一主线从环境准备开始逐步实现一个最小可运行的留言提交系统并配套常见的排错清单和工程化建议。学完后你可以把这套流程迁移到图书管理、用户反馈、信息登记等常见 PHP 后端场景中。1. PHP 后端学习绕不开的这条链路1.1 为什么前端基础会出现在 PHP 后端教程里很多初学者会疑惑学 PHP 后端为什么还要先学前端基础原因很简单PHP 后端处理的数据绝大多数来自浏览器页面也就是 HTML 表单。用户在一个页面里填写姓名、邮箱、留言内容点击提交按钮浏览器把数据打包成 HTTP 请求发送给服务器PHP 脚本接收这些参数经过校验和格式化后写入 MySQL。这个过程里HTML 表单负责“采集”PHP 负责“处理”MySQL 负责“存储”。如果完全不懂表单的 action、method、input 的 name 属性后端代码就不知道该去哪里取数据。这里说的前端基础不是要求你精通 CSS 布局或者 JavaScript 动画而是至少要理解页面如何向后端发起请求、字段如何命名、GET 和 POST 有什么区别、用户输入的数据到了后端是什么形态。把这几个问题搞清楚前后端之间的“数据管道”才能打通。1.2 后端接口到底解决什么问题“后端提供接口”这句话在招聘要求和项目文档里经常出现。接口可以理解为一个 URL 规则前端按照约定的参数发起请求后端处理完业务逻辑后返回结果。在传统 PHP 项目中表单提交到submit.phpsubmit.php处理完返回一个 HTML 页面这就是一次接口调用。在前后端分离项目中PHP 后端只写 API 接口返回 JSON 数据前端再用 JavaScript 渲染页面。两者背后的本质是一样的传入参数 - 处理逻辑 - 返回结果。所以入门阶段不要被“接口”这个概念吓住。你写的index.php接收 POST 参数并插入数据库它就是一个最朴素的接口实现。先把这个请求处理模型理解透之后再学习 RESTful 风格、返回 JSON、接口鉴权都是在这个基础上做扩展。1.3 本教程最终要完成的最小项目为了让整条链路可复现这篇教程会实现一个“用户留言提交系统”。用户在前端页面填写姓名、邮箱、手机号、留言内容提交后由 PHP 做服务端校验再通过正则表达式检查手机号等格式最后把数据写入 MySQL并在页面下方展示最近的留言列表。这个项目规模不大但覆盖了 PHP 后端开发中最常见的几个环节前端表单的提交方式PHP 接收并过滤请求参数服务端表单验证正则表达式格式校验PDO 连接 MySQL 并写入数据从 MySQL 查询数据并安全输出到页面完成这个小项目之后你可以把它扩展成留言板、报名系统、图书管理系统也可以把处理逻辑拆分成独立的控制器和服务类逐步向工程化方向靠近。2. 环境准备PHP、MySQL 和 Web 服务器先跑起来2.1 集成环境与独立部署怎么选PHP 程序不能像普通脚本一样直接双击运行它需要 Web 服务器Apache 或 Nginx来响应 HTTP 请求然后把请求交给 PHP 解释器处理PHP 再访问 MySQL。本地学习阶段最省事的方式是使用集成环境比如 Windows 平台的 phpStudy、XAMPP、WAMPmacOS 平台的 MAMP。这类工具把 Apache/Nginx、PHP、MySQL 打包在一起一键启动适合快速跑通项目。生产环境则需要独立部署。常见组合是 Nginx PHP-FPM MySQLPHP-FPM 负责接收 Nginx 转发过来的 PHP 请求并执行。独立部署的优点是组件分离、资源隔离、方便监控扩容但对刚入门的同学来说前期先用集成环境把业务逻辑跑通再学习独立部署学习曲线更平滑。使用场景推荐方式理由本地学习集成环境启动快配置少一装即可用本地开发调试集成环境或 Docker可随时重置依赖隔离测试环境Docker 或独立部署与生产环境保持一致生产环境独立部署权限控制、日志、监控更灵活2.2 本教程使用的 PHP 和 MySQL 版本基线本教程代码基于 PHP 8.0 以上版本编写MySQL 使用 5.7 或 8.0 都可以。如果你下载的集成环境自带的是 PHP 7.4多数代码也能运行但要注意 PHP 8 对数组访问、字符串函数有一些行为变化遇到警告时先检查版本。有一个历史问题需要特别注意PHP 7.0 开始已经移除了mysql_*系列函数使用mysql_connect()会在运行时报“Call to undefined function”。现在连接 MySQL 应该使用mysqli扩展或PDO扩展本教程统一使用 PDO因为它支持预处理语句能有效避免 SQL 注入问题。安装完成后在命令行执行以下命令确认环境php -v mysql --version php -m | grep pdo_mysql php -m | grep mysqli第一条命令输出 PHP 版本信息第二条输出 MySQL 客户端版本。后面两条命令检查 PHP 是否加载了数据库扩展。如果pdo_mysql和mysqli都没有输出说明 PHP 环境里数据库扩展没有开启需要在集成环境的面板中启用扩展否则后续连数据库必然失败。2.3 项目目录与访问入口集成环境通常会提供一个网页根目录例如 XAMPP 的htdocs目录、phpStudy 的WWW目录。把项目文件放在这个目录下才能通过浏览器访问。本教程的项目目录建议命名为php-demo在浏览器里访问路径通常为http://localhost/php-demo/index.php如果你的 Apache 使用了 8080 端口那么访问地址就是http://localhost:8080/php-demo/index.php端口冲突是新手常见问题。80 端口经常被其他程序占用遇到“无法访问站点”之类的问题时先检查集成环境的端口配置并把项目文件放在正确的根目录下。3. MySQL 设计与 PHP 连接先解决数据写到哪、从哪查3.1 建库建表字符集要在一开始就定对MySQL 中字符集设置直接影响中文是否乱码。入门阶段最容易踩的坑是数据库使用默认字符集写入中文后页面显示一堆问号。原因往往是数据库、数据表、连接字符集三者没有统一。推荐在创建数据库时显式指定utf8mb4它是utf8的超集支持中文、生僻字和 Emoji 表情CREATE DATABASE IF NOT EXISTS php_demo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;接着创建留言表。表结构要与表单字段对应保存用户提交的姓名、邮箱、手机号、留言内容和创建时间USE php_demo; CREATE TABLE IF NOT EXISTS messages ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(30) NOT NULL COMMENT 姓名, email VARCHAR(100) NOT NULL COMMENT 邮箱, phone VARCHAR(20) DEFAULT COMMENT 手机号, content VARCHAR(200) NOT NULL COMMENT 留言内容, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), KEY idx_created_at (created_at) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT留言表;字段类型的选择要根据实际数据长度来定。name用 VARCHAR(30) 限制长度避免用户提交超长内容拖慢查询phone不一定会填写所以允许为空并设置默认值空字符串content是留言正文VARCHAR(200) 适合短留言如果要做长文本评论应该改成 TEXT。3.2 字段设计要匹配表单需求字段名类型含义关键约束idINT UNSIGNED AUTO_INCREMENT主键自增防止重复nameVARCHAR(30)姓名NOT NULLemailVARCHAR(100)邮箱NOT NULLphoneVARCHAR(20)手机号可空默认空串contentVARCHAR(200)留言内容NOT NULLcreated_atDATETIME创建时间默认当前时间字段设计时不要把所有东西都存成 VARCHAR。比如手机号虽然看似“数字”但它不需要参与数学运算用字符串保存更合适因为电话号码可能出现86前缀或座机格式。日期时间用 DATETIME 类型排序和区间查询都更方便。3.3 用 PDO 连接 MySQL而不是继续用 mysql_* 函数PHP 连接 MySQL 最推荐的方式是 PDO。PDO 是一个数据库访问抽象层它支持 MySQL、PostgreSQL、SQLite 等数据库开发者切换数据库时不用重写全部 SQL 逻辑。更重要的是PDO 的预处理语句可以把 SQL 结构和数据分开。下面这段代码演示了 PDO 连接 MySQL 的基本写法?php $dsn mysql:host127.0.0.1;port3306;dbnamephp_demo;charsetutf8mb4; $user root; $pass ; $options [ PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES false, ]; $pdo new PDO($dsn, $user, $pass, $options);charsetutf8mb4是连接字符集它必须和数据库、数据表的字符集一致。PDO::ATTR_ERRMODE设置为ERRMODE_EXCEPTION后SQL 出错时会抛出异常开发阶段更容易定位问题。PDO::ATTR_EMULATE_PREPARES设置为 false可以让 MySQL 使用真正的预处理而不是在 PHP 端模拟安全性更高。3.4 连接信息的组织方式配置独立成文件数据库配置不应该散落在每个 PHP 文件里否则修改密码或切换数据库时要到处改。习惯上把配置放在独立文件config.php中再用require引入。?php define(DB_HOST, 127.0.0.1); define(DB_PORT, 3306); define(DB_NAME, php_demo); define(DB_USER, root); define(DB_PASS, ); define(DB_CHARSET, utf8mb4);这里使用常量而不是变量是为了防止配置在运行过程中被意外修改。在学习环境里MySQL 账号密码可能是root和空密码生产环境必须使用独立账号并限制这个账号只能访问项目数据库不能使用 root。4. 前端表单只负责采集数据后端验证才是数据防线4.1 表单如何把数据交给后端action 与 methodHTML 表单的核心属性有两个action决定把数据发送到哪个 URLmethod决定用什么 HTTP 方法发送。form actionindex.php methodpost label forname姓名/label input typetext idname namename button typesubmit提交留言/button /form用户点击提交后浏览器会取出表单里所有带name属性的控件拼成参数发送到action指定的地址。后端 PHP 中通过$_POST[name]就能拿到输入框里的内容。所以表单控件的name属性是前后端约定的关键后端取不到数据首先检查表单控件的name是否写对了。4.2 GET 和 POST 的差异要按用途选GET 和 POST 是表单最常用的两种提交方式区别不仅仅是“参数在 URL 里”这么简单。对比项GETPOST参数位置URL 查询字符串请求体可见性地址栏可见地址栏不可见长度限制受浏览器 URL 长度限制相对宽松适用场景搜索、筛选、分页提交数据、创建/更新资源幂等性重复请求影响相同重复提交可能产生多条数据搜索框适合用 GET这样用户可以复制带搜索词的 URL 分享给其他人新增留言、注册、登录这类修改数据的操作必须用 POST避免刷新页面时重复提交也避免敏感信息直接暴露在 URL 里。4.3 前端 required 和后端校验不是同类东西HTML5 提供一个required属性可以让浏览器在用户点击提交时弹出提示阻止空表单发送input typetext namename required方便归方便但前端校验只能算“用户体验优化”不能当作安全边界。用户可以禁用 JavaScript也可以直接构造 HTTP 请求绕过浏览器把垃圾数据 POST 到你的后端。后端是数据进入数据库的最后一关校验必须放在 PHP 代码里。正确的态度是前端required让正常用户少填错后端逻辑保证所有数据都经过校验。4.4 服务端表单验证的基本流程服务端验证不是简单判断“空不空”而是按固定流程处理接收原始参数。去掉首尾空白。检查必填项。校验格式。限制长度。数据合法后写入数据库。有错误时把错误信息返回给用户。$errors []; $name trim($_POST[name] ?? ); $email trim($_POST[email] ?? ); $phone trim($_POST[phone] ?? ); $content trim($_POST[content] ?? ); if ($name ) { $errors[] 姓名不能为空; } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors[] 邮箱格式不正确; } if ($phone ! !preg_match(/^1[3-9]\d{9}$/, $phone)) { $errors[] 手机号格式不正确; }使用$_POST[name] ?? 是因为$_POST数组访问不存在的键时PHP 8 会产生警告。用空合并运算符可以安全地拿到默认值。这里把所有错误都收集到$errors数组里最后统一判断避免只提示一个错误就中断让用户反复提交。5. 用正则表达式做格式校验先懂场景再记语法5.1 PHP 中正则表达式的基本写法正则表达式是用来描述字符串规则的表达式。PHP 中常用的函数是preg_match()它检查字符串是否匹配某个模式if (preg_match(/^1[3-9]\d{9}$/, $phone)) { echo 手机号格式正确; }PHP 的正则模式必须放在一对定界符里。定界符常用/也可以使用#、~等其他符号。如果规则本身包含大量斜杠比如校验 URL使用#定界符可以少写很多转义if (preg_match(#^https?://#, $url)) { echo 这是一个 http 或 https 链接; }模式中的^表示字符串开始$表示字符串结束。手机号规则里的[3-9]表示第二位是 3 到 9 之间的数字\d{9}表示 9 位数字。加上^和$后整个字符串必须完全匹配而不是只匹配其中一部分。5.2 常用校验正则手机号、邮箱、用户名、IP、密码强度下面是一组常见的校验正则可以直接在实际项目中使用// 手机号1 开头第二位 3-9后面 9 位数字 $phonePattern /^1[3-9]\d{9}$/; // 邮箱常见形式 $emailPattern /^[\w.-][A-Za-z0-9-](\.[A-Za-z0-9-])$/; // 中文姓名2 到 10 个中文字符必须加 u 修饰符 $namePattern /^[\x{4e00}-\x{9fa5}]{2,10}$/u; // IPv4 地址 $ipPattern /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/; // 密码长度8-20 个非空白字符 $passwordLengthPattern /^\S{8,20}$/; // 密码同时包含字母和数字 $hasLetter preg_match(/[A-Za-z]/, $password); $hasDigit preg_match(/\d/, $password);校验目标常用写法说明手机号^1[3-9]\d{9}$匹配中国大陆手机号常见格式邮箱^[\w.-][A-Za-z0-9-](\.[A-Za-z0-9-])$基本邮箱格式中文姓名^[\x{4e00}-\x{9fa5}]{2,10}$必须加u修饰符IPv4分段判断 0-255比用\d{1,3}更严谨密码强度长度 字符类型组合判断通常需要多个条件配合IPv4 校验不能写成^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$因为999.999.999.999也能通过。正确做法是把每段限定在 0 到 255 之间再通过.连接。这正好对应“输入一个字符串判断它是不是一个 IP 地址”这类练习题这类题目考的不是背语法而是“合法范围”的表达能力。5.3 正则表达式容易踩的三个坑第一个坑是处理中文时不加u修饰符。PHP 的 PCRE 默认按单字节处理中文在 UTF-8 编码下占多个字节直接匹配[\x{4e00}-\x{9fa5}]会失效。加上u修饰符后正则引擎才会按 UTF-8 字符匹配。第二个坑是定界符和模式内容冲突。例如用/做定界符去匹配 URLhttps://example.com时里面的斜杠会提前结束模式。要么转义斜杠要么换用#定界符。推荐后者可读性更好。第三个坑是滥用正则做复杂解析。正则适合判断字符串“是否符合某种格式”不适合解析 HTML、JSON 这类有嵌套结构的文本。比如用正则去 HTML 里提取文章内容很容易因为标签属性顺序不同而漏掉或匹配错误。遇到这种需求应该使用 PHP 的DOMDocument或 JSON 解析函数。5.4 不是所有格式校验都该用正则正则表达式不是万能的有些校验用原生函数更简单也更可靠。邮箱校验优先使用filter_var($email, FILTER_VALIDATE_EMAIL)它能识别很多正则很难写全的边界情况。URL 校验也可以使用FILTER_VALIDATE_URL。数值范围校验用is_numeric()、filter_var()或者直接比较大小。选型原则是一个函数能解决的问题不要硬写正则。正则主要用在手机号、身份证、密码组成规则、代码字符串匹配这类“自定义规则”场景。6. 完整案例留言提交从表单到 MySQL 的最小闭环6.1 项目目录结构目录结构越简单越容易看清楚数据流。学习阶段先不引入 MVC 架构只把配置、数据库连接、页面入口分开php-demo/ ├─ config.php ├─ db.php └─ index.phpconfig.php数据库连接参数。db.php创建 PDO 连接对象的函数。index.php表单展示、表单处理、留言列表展示都先放在这个文件里。等这段流程跑通后再考虑把处理逻辑抽到独立控制器把 HTML 抽到模板文件。学习阶段先跑通闭环工程规范下一步再逐步引入。6.2 配置文件与数据库连接先创建config.php?php define(DB_HOST, 127.0.0.1); define(DB_PORT, 3306); define(DB_NAME, php_demo); define(DB_USER, root); define(DB_PASS, ); define(DB_CHARSET, utf8mb4);再创建db.php提供一个返回 PDO 对象的函数?php require_once __DIR__ . /config.php; function db(): PDO { $dsn sprintf( mysql:host%s;port%s;dbname%s;charset%s, DB_HOST, DB_PORT, DB_NAME, DB_CHARSET ); $options [ PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES false, ]; return new PDO($dsn, DB_USER, DB_PASS, $options); }db()函数每次调用都会创建一个新的 PDO 连接。在简单项目里这足够用但要注意高并发场景下应该使用连接池或长连接避免频繁建立和断开数据库连接。6.3 表单展示页采集字段并展示已有留言index.php是核心文件。它同时承担三个职责处理 POST 请求、展示表单、展示留言列表。学习阶段这样写最直观代码注释也方便理解。?php require __DIR__ . /db.php; $errors []; $success ; $name ; $email ; $phone ; $content ; if ($_SERVER[REQUEST_METHOD] POST) { $name trim($_POST[name] ?? ); $email trim($_POST[email] ?? ); $phone trim($_POST[phone] ?? ); $content trim($_POST[content] ?? ); if ($name ) { $errors[] 姓名不能为空; } elseif (mb_strlen($name) 30) { $errors[] 姓名不能超过 30 个字符; } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors[] 邮箱格式不正确; } if ($phone ! !preg_match(/^1[3-9]\d{9}$/, $phone)) { $errors[] 手机号格式不正确; } if ($content ) { $errors[] 留言内容不能为空; } elseif (mb_strlen($content) 200) { $errors[] 留言内容不能超过 200 字; } if (empty($errors)) { $stmt db()-prepare( INSERT INTO messages (name, email, phone, content, created_at) VALUES (:name, :email, :phone, :content, NOW()) ); $stmt-execute([ :name $name, :email $email, :phone $phone, :content $content, ]); $success 提交成功留言已保存。; $name $email $phone $content ; } } $rows db()-query( SELECT name, content, created_at FROM messages ORDER BY id DESC LIMIT 20 )-fetchAll(); ?6.4 HTML 模板安全输出表单和列表处理完数据后再输出 HTML。这块的关键是使用htmlspecialchars()转义所有需要回显的用户数据防止 XSS 脚本注入。!DOCTYPE html html langzh-CN head meta charsetUTF-8 titlePHP 留言提交演示/title style body { font-family: sans-serif; max-width: 640px; margin: 40px auto; } .field { margin-bottom: 12px; } label { display: inline-block; width: 80px; } input, textarea { width: 300px; padding: 6px; } button { padding: 8px 20px; cursor: pointer; } .error { color: #b00020; } .success { color: #1e7e34; } /style /head body h1留言提交/h1 ?php if (!empty($errors)): ? div classerror ul ?php foreach ($errors as $error): ? li?php echo htmlspecialchars($error, ENT_QUOTES, UTF-8); ?/li ?php endforeach; ? /ul /div ?php endif; ? ?php if ($success ! ): ? p classsuccess?php echo htmlspecialchars($success, ENT_QUOTES, UTF-8); ?/p ?php endif; ? form actionindex.php methodpost div classfield label forname姓名/label input typetext idname namename value?php echo htmlspecialchars($name, ENT_QUOTES, UTF-8); ? /div div classfield label foremail邮箱/label input typeemail idemail nameemail value?php echo htmlspecialchars($email, ENT_QUOTES, UTF-8); ? /div div classfield label forphone手机号/label input typetext idphone namephone value?php echo htmlspecialchars($phone, ENT_QUOTES, UTF-8); ? /div div classfield label forcontent留言/label textarea idcontent namecontent rows5?php echo htmlspecialchars($content, ENT_QUOTES, UTF-8); ?/textarea /div button typesubmit提交留言/button /form h2最近留言/h2 ?php if (empty($rows)): ? p还没有留言来写第一条吧。/p ?php else: ? ul ?php foreach ($rows as $row): ? li strong?php echo htmlspecialchars($row[name], ENT_QUOTES, UTF-8); ?/strong span?php echo htmlspecialchars($row[created_at], ENT_QUOTES, UTF-8); ?/span p?php echo nl2br(htmlspecialchars($row[content], ENT_QUOTES, UTF-8)); ?/p /li ?php endforeach; ? /ul ?php endif; ? /body /html这里有两个细节值得注意。第一value属性里的旧值也要使用htmlspecialchars()转义否则用户输入的会破坏 HTML 属性结构。第二留言内容用nl2br()把换行符转换为br让用户输入的多行内容能正确展示同时先转义再转换避免脚本注入。6.5 运行与验证看完这条闭环的预期结果启动 Apache 和 MySQL 后在浏览器访问http://localhost/php-demo/index.php按下面几种场景分别测试测试场景输入内容预期结果正常提交姓名张三邮箱zhangsanexample.com手机号13800138000留言学习 PHP 后端页面显示提交成功列表出现这条留言空姓名清空姓名页面显示“姓名不能为空”错误邮箱输入abc页面显示“邮箱格式不正确”手机号非法输入12345页面显示“手机号格式不正确”中文留言输入多行中文内容列表按换行格式展示不乱码如果这些场景都符合预期说明“前端表单 - PHP 验证 - 正则校验 - MySQL 入库 - 页面查询展示”这条链路已经跑通。7. 常见问题排查从现象倒推根因7.1 页面白屏或没有输出现象访问index.php时浏览器空白没有任何提示。可能原因有很多PHP 文件语法错误、数据库连接异常被静默处理、PHP 错误输出被关闭。开发环境应该把错误显示打开在index.php开头临时加入ini_set(display_errors, 1); error_reporting(E_ALL);也可以直接查看 PHP 错误日志。集成环境一般会在日志目录记录错误而不是直接输出到浏览器。排查时先确认错误显示级别再逐行检查语法尤其是分号和引号是否成对。7.2 提交后数据没有进入数据库现象页面没有报错但 MySQL 表里查不到数据。先检查提交方式。表单使用的是methodpost后端就应该用$_POST接收。如果表单方法是 GET而代码读取 POST参数永远是空。接着检查字段名。表单控件nameemail后端取$_POST[email]大小写和拼写都必须一致。如果 SQL 语句出错PDO 在ERRMODE_EXCEPTION模式下会抛出异常。可以在插入代码周围加try/catch并打印异常信息。常见错误是字段名写错或者content长度超过 VARCHAR(200) 的限制MySQL 在严格模式下会拒绝插入。问题现象常见原因检查方式处理建议提交后无数据form method 与后端 GET/POST 不一致检查 HTML 和 PHP 读取方式统一使用 POST插入失败但无提示PDO 异常模式没有开启检查 ATTR_ERRMODE 配置开发环境开启 EXCEPTION 模式中文乱码库表连接字符集不一致检查表字符集和 DSN charset统一使用 utf8mb47.3 中文乱码现象数据库中中文正常但页面显示乱码或者页面正常数据库里是???。乱码通常来自三个层面的字符集不一致数据库表字符集、PHP 连接字符集、HTML 页面编码。检查顺序创建数据库时是否指定utf8mb4。PDO 的 DSN 是否包含charsetutf8mb4。HTML 的meta charsetUTF-8是否存在。如果数据已经以错误字符集写入删除数据后重建表再重新插入一遍。7.4 正则匹配不上现象格式明明没问题preg_match()却返回 0。先检查定界符。模式没有放在定界符里会导致preg_match()直接返回 false。再检查修饰符。匹配中文时没有加u修饰符是典型的匹配失效原因。可以在命令行中单独验证正则php -r var_dump(preg_match(/^1[3-9]\d{9}$/, 13800138000));如果输出int(1)说明正则本身没问题如果规则包含反斜杠、引号在 PHP 单引号字符串里要注意转义规则。7.5 表单验证没有生效现象前端required提示正常但后端校验规则没有
返回列表