PHP网站乱码核心是UTF-8链路断裂:一、PHP文件须为UTF-8无BOM;二、PHP开头用header()声明charset=utf-8;三、HTML中<meta charset="UTF-8">;四、MySQL用utf8mb4并正确连接;五、Web服务器与php.ini设默认UTF-8。

PHP网站部署后出现乱码,核心原因是字符编码链路断裂——从文件保存、HTTP响应、HTML声明、数据库连接到服务器配置,任一环节未统一为UTF-8(尤其是utf8mb4),就可能在页面上显示为问号、方块或错位符号。解决关键不是逐个试错,而是按执行顺序系统检查。
PHP源文件必须是UTF-8无BOM
这是起点,也是最容易被忽略的一环。带BOM的UTF-8文件会在输出前悄悄输出\xEF\xBB\xBF三个字节,导致header()调用失败,并引发“headers already sent”警告。
- 用VS Code、Notepad++或Sublime Text打开所有PHP文件,在状态栏确认编码显示为“UTF-8”且明确标注“无BOM”
- 若显示“UTF-8 with BOM”或“GBK”,选择“另存为”→ 手动选中“UTF-8(无BOM)”→ 覆盖原文件
- Linux下可快速验证:
file -i index.php,输出应为charset=utf-8,不含with bom
HTTP响应头与HTML meta必须同步声明UTF-8
浏览器优先信任HTTP响应头中的Content-Type,但<meta charset>是重要后备。二者不一致时,部分浏览器会降级处理。
- 在每个PHP文件最顶部(任何输出之前,包括空行、空格、
<?php前的空白)添加:header('Content-Type: text/html; charset=utf-8'); - 在HTML的
<head>内紧贴开头位置写:<meta charset="UTF-8">(不要用http-equiv旧写法) - 用curl验证响应头:
curl -I https://yoursite.com/index.php,确认返回中含Content-Type: text/html; charset=utf-8
MySQL连接与表结构必须使用utf8mb4
MySQL的utf8实际是utf8mb3,不支持emoji和部分生僻汉字;真正兼容UTF-8的是utf8mb4。只改表字符集不够,连接层也必须指定。
立即学习“PHP免费学习笔记(深入)”;
- 建库时指定:
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 建表/改表字段时用:
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - PHP连接后立即设置(mysqli):
mysqli_set_charset($conn, 'utf8mb4');
或PDO DSN中加入:mysql:host=localhost;dbname=test;charset=utf8mb4 - 避免用
SET NAMES utf8——它只设utf8mb3,应改为SET NAMES utf8mb4
服务器与PHP运行环境需默认支持UTF-8
当以上都正确,仍乱码,说明底层环境未兜底。Apache/Nginx和PHP自身需明确告知“默认就是UTF-8”。
- Apache:修改
httpd.conf,将AddDefaultCharset改为:AddDefaultCharset UTF-8 - Nginx:在server块中添加:
charset utf-8; - PHP:在
php.ini中确认:default_charset = "UTF-8"extension=mbstring(取消注释)
并在脚本开头加:mb_internal_encoding('UTF-8');



















