php编码问题需四层统一:文件编码(utf-8无bom)、运行时mb_internal_encoding('utf-8')、http头content-type与html meta一致为utf-8、mysql连接用utf8mb4并确保服务端及表字段字符集匹配。

PHP 文件本身编码不一致导致解析失败
旧项目常混用 GBK、GB2312、UTF-8(无 BOM)甚至带 BOM 的 UTF-8,PHP 解析器遇到非 ASCII 字符(如中文注释、字符串、变量名)时直接报 Parse error: syntax error, unexpected 'xxx' 或 Cannot declare class xxx because the name is already in use(BOM 被当作文本输出导致 header 冲突)。
- 用编辑器(如 VS Code、Notepad++)检查文件实际编码:右下角显示“UTF-8”“GBK”等,**不要只看文件保存时选的选项**
- 批量检测命令行(Linux/macOS):
file -i *.php或enca -L zh *.php(需安装 enca) - 统一转为
UTF-8 without BOM:VS Code 中点击右下角编码 → “Save with Encoding” → 选UTF-8(注意不是UTF-8 with BOM) - 特别注意:.php 文件里若有
<?php echo "你好"; ?>这类中文字符串,其所在文件必须与该字符串编码一致,否则运行时报Warning: mb_strlen(): Invalid encoding "UTF-8"类错误
PHP 运行时默认编码未设导致 mbstring 函数出错
即使文件是 UTF-8,mb_strlen()、mb_substr() 等函数仍可能报错或返回异常结果,因为 PHP 默认内部编码是 ISO-8859-1,而 mbstring.func_overload 已废弃,不能靠它“自动转换”。
- 确认当前 mbstring 编码:
var_dump(mb_internal_encoding());—— 旧项目常为ISO-8859-1 - 在入口文件(如
index.php)最开头加:mb_internal_encoding('UTF-8');(注意:必须在任何输出前,且不能放在require后) - 若用 Composer 自动加载,可在
composer.json的autoload.files中提前引入一个设置编码的文件 - 避免在函数内反复调用
mb_internal_encoding(),它有开销;全局设一次即可
HTTP 输出头与 HTML meta 编码不匹配引发乱码
浏览器看到中文乱码,常见原因是 PHP header() 发送的 Content-Type 和 HTML 中 <meta charset="xxx"> 不一致,或压根没发头。
- 检查是否已发送头:
headers_sent($file, $line)—— 若返回 true,说明已有输出(空格、BOM、echo),不能再调用header() - 正确设置响应头:
header('Content-Type: text/html; charset=UTF-8');(注意拼写是charset,不是char-set或encoding) -
<meta charset="UTF-8">必须放在最前面,且不能写成<meta http-equiv="Content-Type" content="text/html; charset=GBK">(过时写法,优先级低于 HTTP 头) - CLI 模式下无需设 header,但若项目含
echo "<meta...>"</meta...>,要确保该字符串本身编码正确,否则终端显示乱码
数据库连接编码未同步导致读写乱码
PHP 文件和页面都设了 UTF-8,但 MySQL 查询出来的中文仍是问号或 Mojibake,基本锁定是连接层编码没对齐。
立即学习“PHP免费学习笔记(深入)”;
- MySQLi 连接后立即执行:
$mysqli->set_charset('utf8mb4');(不是utf8,后者仅支持 3 字节 UTF-8) - PDO 构造时传 DSN 参数:
new PDO("mysql:host=localhost;charset=utf8mb4", $user, $pass);,同时确保SET NAMES utf8mb4也执行(PDO 默认不自动发) - 检查 MySQL 服务端配置:确认
my.cnf中collation-server = utf8mb4_unicode_ci且character-set-server = utf8mb4 - 表和字段字符集也要是
utf8mb4:SHOW CREATE TABLE users;查看,不是则用ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
旧项目迁移时,编码问题往往不是单点故障,而是文件编码、运行时编码、HTTP 头、数据库连接四层叠加出错。最容易被忽略的是 BOM 隐藏字符 和 MySQL 的 utf8 ≠ utf8mb4 —— 这两个点一错,其他全设对也白搭。











