php表单中文乱码主因是请求体编码与php解析不匹配;需先用var_dump($_post)确认是否真乱码,再检查html charset、form accept-charset、响应头及json等特殊场景。

PHP 表单提交中文乱码,90% 是因为请求体编码和 PHP 解析方式不匹配,不是简单的 header 或 meta 能解决的。
检查 $_POST 里是不是真乱码,还是只是显示问题
很多人一看到浏览器输出是 “æä¸ªæ±å” 就断定是乱码,其实可能是输出时没设 charset,而 $_POST 本身是好的。
- 用
var_dump($_POST)看原始值,如果里面已经是问号或 ,说明接收阶段就坏了 - 如果
$_POST里中文看着正常(比如显示为“测试”),但 echo 出来变成乱码,重点查响应头和 HTML 的Content-Type - 加一句
header('Content-Type: text/html; charset=utf-8');再试,别只靠<meta charset="utf-8">—— 它对 POST 接收完全无效
确保表单提交用的是 UTF-8 编码(accept-charset 和页面编码一致)
浏览器默认按当前页面编码提交表单。如果 HTML 是 GBK,它就会把中文用 GBK 编码发过去,而 PHP 默认按 UTF-8 解析 —— 必然错。
- HTML 页面顶部必须声明:
<meta charset="utf-8">(不能写成http-equiv那种老写法) - 表单标签显式指定:
<form accept-charset="UTF-8"></form>—— 这个属性在某些旧浏览器(如 IE8)里很关键 - 避免用 JS 动态 submit 却没设置
form.acceptCharset = 'UTF-8',否则可能继承父页面意外编码
PHP 没有自动转码,$_POST 值就是原始字节流
PHP 不会根据 Content-Type: application/x-www-form-urlencoded; charset=utf-8 自动转换 $_POST。这个 header 是可选的,且多数浏览器根本不会发它。
立即学习“PHP免费学习笔记(深入)”;
- PHP 5.6+ 可通过
default_charset = "UTF-8"影响部分输出行为,但对$_POST解析无影响 - 不要依赖
mb_http_input()或mb_detect_encoding()去“猜”编码 —— POST 数据没有 BOM,猜错率极高 - 最稳做法:确认前端发的是 UTF-8,后端就当它是 UTF-8;如果必须兼容老系统传 GBK,用
iconv('GBK', 'UTF-8//IGNORE', $_POST['name'])显式转,别试图自动识别
JSON 提交(application/json)要单独处理
用 fetch 或 axios 发 JSON 时,$_POST 是空的 —— 因为 PHP 不解析 JSON 请求体。
- 得用
$raw = file_get_contents('php://input');读原始数据 - 再用
json_decode($raw, true)解析,注意检查json_last_error() - 此时编码完全取决于你发请求时 body 的字节,确保
JSON.stringify({name: "张三"})是 UTF-8 字符串(现代 JS 默认就是)
真正麻烦的从来不是“怎么设 UTF-8”,而是前后端在某个环节悄悄用了不同编码,又没做校验。比如 Nginx 的 charset 指令、Apache 的 AddDefaultCharset、MySQL 连接时的 SET NAMES,任何一个漏掉,都会让中文在某个链路里被二次破坏。











