POST中文乱码本质是UTF-8编码链路断裂,需四步对齐:1. PHP文件存为UTF-8无BOM;2. 入口首行设mb_internal_encoding('UTF-8')和header('Content-Type: text/html; charset=utf-8');3. HTML加<meta charset="UTF-8">且表单设accept-charset="UTF-8";4. 异常时用php://input手动解析。

1. PHP 文件必须保存为 UTF-8 无 BOM
FrankenPHP 对 BOM 更敏感:开头的 \xEF\xBB\xBF 会被当作响应体提前输出,导致 header() 失效,后续所有字符集声明都白搭。
- 用 VS Code 打开 PHP 文件,右下角查看编码 → 若显示 “UTF-8 with BOM” 或 “GBK”,点击切换 → 选 “Save with Encoding” → “UTF-8”(注意不是 “UTF-8 with BOM”)
- Linux 下验证:
file -i your_script.php,输出应为charset=utf-8,不含with bom - 绝对不要用 Windows 记事本编辑或保存 PHP 文件
2. 入口文件顶部强制统一内部编码与响应头
FrankenPHP 不自动加载 php.ini 的 default_charset,也不保证 mbstring 默认生效,必须手动显式设置。
- 在
public/index.php(或你实际入口)最顶部第一行(任何输出之前)写:
<?php
if (function_exists('mb_internal_encoding')) {
mb_internal_encoding('UTF-8');
}
header('Content-Type: text/html; charset=utf-8');
// 或 API 场景用:
// header('Content-Type: application/json; charset=utf-8');
- 不要依赖
ob_start()补救 —— 它掩盖问题,不解决根源
3. HTML 表单和请求头必须明确 UTF-8
浏览器按什么编码发,FrankenPHP 就按什么解;不声明,就可能 fallback 到 latin1 或系统 locale。
立即学习“PHP免费学习笔记(深入)”;
- HTML 页面
<head>中必须有:<meta charset="UTF-8">(放在<title>前) - 表单标签显式声明:
<form method="post" accept-charset="UTF-8"> - 用 Chrome DevTools → Network → 点开 POST 请求 → 查看 Request Headers → 确认
Content-Type是application/x-www-form-urlencoded; charset=UTF-8(不是缺 charset,也不是 GBK)
4. 不要信任 $_POST 自动解码,必要时手动还原原始字节
FrankenPHP 使用标准 SAPI 解析逻辑,但若前端发送异常编码(如 URL 中含未 encode 的中文),或 Nginx 层做了重写,$_POST 可能已损坏。此时应绕过自动解析,读取原始 body。
- 当发现
$_POST['name']是乱码(如æµè¯)且上述三点都确认无误时,改用:
$raw = file_get_contents('php://input');
if (!empty($raw) && stripos($_SERVER['CONTENT_TYPE'] ?? '', 'application/x-www-form-urlencoded') === 0) {
$data = [];
parse_str($raw, $data);
// 此时 $data['name'] 是原始 UTF-8 字节,可直接用
}
- 如果仍需处理 JSON 提交,记得加
json_decode(ltrim($raw, "\xEF\xBB\xBF"), true)清掉可能的 BOM



















