PHP乱码需分步解决:先用VS Code检测并清除BOM;再在脚本开头用header()设响应头并用curl验证;接着调用mb_internal_encoding('UTF-8')统一多字节处理;数据库连接须用utf8mb4并确保表字符集匹配;最后对已乱码字符串用mb_detect_encoding、mb_convert_encoding等函数修复。

确认PHP文件本身是否含BOM或编码错乱
用VS Code打开出问题的PHP文件,右下角查看当前编码显示——它只是编辑器猜测值,不可信。按Ctrl+Shift+P→输入“Reopen with Encoding”→依次尝试“UTF-8”“UTF-8 with BOM”“GBK”,观察中文是否突然正常显示。
若选“UTF-8 with BOM”时中文正常,说明文件实际含BOM头(EF BB BF三个隐藏字节),必须清除:右下角点击编码名→“Save with Encoding”→选“UTF-8”(注意不是“UTF-8 with BOM”)→保存覆盖。
【BOM一旦写入,PHP会把它当普通输出,导致header()调用直接报“Headers already sent”错误,后续所有charset设置全部失效】
检查HTTP响应头是否真正生效
在PHP脚本最开头(任何echo、print、空行、HTML之前)插入:header('Content-Type: text/html; charset=utf-8');
立即学习“PHP免费学习笔记(深入)”;
然后用curl命令验证真实响应头:curl -I http://yoursite.com/your_script.php,看返回中是否有Content-Type: text/html; charset=utf-8这一行。
如果没出现,说明前面有不可见输出(BOM、空格、换行)或已调用过其他输出函数。此时需逐个排查被include的配置文件——哪怕一个config.php带BOM,整个主脚本的header都会失败。
强制统一PHP内部多字节字符串处理编码
在脚本开头、header()之后立即添加:
mb_internal_encoding('UTF-8');
这一步不能省略。PHP 7.3默认内部编码是ISO-8859-1,所有mb_*函数(如mb_strlen、mb_substr)若不显式设为UTF-8,就会把中文当单字节处理,导致截断、偏移、乱码。
同时检查php.ini中mbstring.func_overload是否为0——若为非零值,strlen等原生函数会被mb系列覆盖,可能破坏加密解密流程中的字节长度计算。
修复数据库查询结果乱码
方法一:mysqli连接后立即执行
$mysqli->set_charset('utf8mb4');
方法二:PDO连接DSN中直接声明
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', $user, $pass);
注意:MySQL的utf8是阉割版(最多3字节),不支持emoji和部分生僻汉字;必须用utf8mb4。如果建表时字段字符集仍是utf8,仅改连接无用——需执行ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
对已读取的乱码字符串做紧急转码
第一步:用mb_detect_encoding($str, ['UTF-8', 'GBK', 'GB2312'], true)探测原始编码。若返回false,说明字符串含非法字节,先用mb_scrub($str)清洗。
第二步:根据探测结果转换,例如检测出是GBK,则执行$fixed = mb_convert_encoding($str, 'UTF-8', 'GBK');
第三步:输出前再次校验mb_check_encoding($fixed, 'UTF-8'),确保结果合法。若仍为false,改用iconv('GBK', 'UTF-8//IGNORE', $str)硬转,丢弃无法映射的字符。



















