php处理utf-8需控制四个环节:文件编码、http响应头、数据库连接、字符串操作函数;header("content-type: text/html; charset=utf-8")须首行输出前调用,且文件必须保存为utf-8 without bom。

PHP处理UTF-8不是靠“学一个函数”,而是靠控制四个关键环节:文件编码、HTTP响应头、数据库连接、字符串操作函数。漏掉任意一环,中文就可能变 ??? 或乱码成 æç±PHP。
header("Content-Type: text/html; charset=UTF-8") 必须放在第一行输出前
这个调用不是可选的,是硬性前置条件。只要在它之前有任何输出(哪怕是一个空格、换行、BOM),PHP就会报 Warning: Cannot modify header information,浏览器收不到charset声明,大概率 fallback 到 GBK,中文立刻失效。
- 确认编辑器保存为
UTF-8 without BOM(VS Code右下角点击编码 → “Save with Encoding” → 选UTF-8) <?php必须是文件第一个字符,前面不能有空行、注释或空格- 不要依赖
ob_start()来“兜底”——它掩盖问题,不解决根源 - 写成
charset=utf8是错的,必须是charset=UTF-8(连字符和大写 U/T/F/8 是规范要求,IE 和部分旧 UA 不认utf8)
MySQL 连接必须用 utf8mb4,不是 utf8
MySQL 的 utf8 是阉割版(实际叫 utf8mb3),最多存 3 字节,不支持 emoji、部分生僻汉字(如「?」「?」)、甚至某些越南文字符。用它建库建表,插入时会被静默截断或转成 ?。
- PDO 连接字符串里必须显式带
charset=utf8mb4:$dsn = "mysql:host=localhost;dbname=test;charset=utf8mb4" - 额外加
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"更稳妥 - MySQL 服务端配置要设
collation-server = utf8mb4_unicode_ci,否则客户端即使连对了,服务端仍可能降级处理 -
ALTER DATABASE ... CHARACTER SET utf8mb4只改库默认值,已有表/字段的字符集不会自动更新,得单独ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4
字符串操作必须用 mb_* 系列函数
PHP 原生函数(strlen、substr、strpos)按字节计算,对 UTF-8 多字节字符会切开字节流,导致乱码或逻辑错误。比如 strlen("你好") 返回 6(每个汉字占 3 字节),但你需要的是字符数 2。
- 统一用
mb_strlen($str, 'UTF-8')、mb_substr($str, 0, 5, 'UTF-8')、mb_strpos($str, '搜索词', 0, 'UTF-8') - 别只靠
mb_internal_encoding('UTF-8')—— 它只影响mb_*函数的默认编码参数,不改变原生函数行为,也不发 HTTP header - 正则匹配含中文时,必须加
u修饰符:preg_match('/^[\p{Han}]+$/u', $str),否则\w或.无法正确识别 Unicode 字符 - 从外部读文件(如 CSV、XML)时,先用
mb_detect_encoding()粗判源编码,再用mb_convert_encoding($content, 'UTF-8', $detected)转,但别迷信mb_detect_encoding(),它常误判;最好明确知道源编码(如 GBK、BIG5)再转
file_put_contents() 写文件不会“自动转UTF-8”
PHP 没有“创建UTF-8文件”的开关。它只是把变量里的字节原样写进磁盘。所以写出来是不是UTF-8,完全取决于你传进去的字符串本身是不是UTF-8字节流。
- 确保 PHP 源文件是
UTF-8 without BOM,里面的中文字符串字面量(如"姓名:张三")才是UTF-8字节 - 用户 POST 上来的数据,要确认表单用了
accept-charset="UTF-8",且服务器没被中间件(如 Nginx、CDN)转码 - 数据库读出的数据,必须已通过
utf8mb4连接获取,才是UTF-8字节流 - 不要手动加 BOM:
"\xEF\xBB\xBF" . $content—— JSON 解析失败、XML 报错、Linux 工具误判,现代环境全不需要 - 验证文件是否真为UTF-8:Linux 下用
file -i filename.txt看charset=utf-8,或hexdump -C filename.txt | head确认开头没有ef bb bf
最易被忽略的是“源头一致性”:PHP 文件编码、HTTP 请求体编码、数据库连接编码、外部 API 响应编码,这四者必须全部是 UTF-8(utf8mb4)。任何一环混入 GBK 或 ISO-8859-1,后续所有 mb_convert_encoding() 都是补救,成本高且不可靠。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











