Hyperf 全链路需统一 UTF-8 编码:PHP 配置 default_charset="UTF-8",数据库连接显式设 charset=utf8mb4,HTTP 请求/响应头声明 charset=utf-8,文件与第三方 SDK 按需转码。

Hyperf 默认使用 UTF-8 编码,但跨平台(如 Windows 开发环境 + Linux 生产环境)或对接外部系统(如旧版数据库、HTTP 接口、Excel 文件)时,常因字符集不一致导致乱码、JSON 解析失败、数据库写入截断等问题。核心不是改 Hyperf 本身,而是统一“输入→处理→输出”全链路的编码约定。
确保 PHP 环境默认使用 UTF-8
Hyperf 基于 Swoole,而 Swoole 的字符串处理依赖 PHP 底层编码行为。需确认:
- PHP 配置中 default_charset = "UTF-8"(php.ini),避免 header() 或 json_encode() 自动补 ISO-8859-1
- CLI 模式下,终端/IDE 的 locale 应为 UTF-8(Linux/macOS 运行
locale | grep UTF;Windows WSL 同理,CMD/PowerShell 需启用 UTF-8 支持) - 禁止在代码中调用
mb_internal_encoding('GBK')等临时切换,会干扰 Hyperf 内部 JSON、Validator、Serializer 组件
数据库连接强制声明 UTF8MB4
MySQL/MariaDB 是重灾区:即使表字符集是 utf8mb4,若连接未声明,Swoole 协程客户端仍可能以 latin1 建立连接。
- 在
config/autoload/databases.php中,为 MySQL 配置显式指定'charset' => 'utf8mb4' - 同时设置
'collation' => 'utf8mb4_unicode_ci',并确保对应数据库、表、字段均为 utf8mb4 - 验证方式:在 Hyperf 命令行中执行
php bin/hyperf.php db:query "SELECT @@character_set_client, @@character_set_connection, @@character_set_results;",三项都应返回utf8mb4
HTTP 请求与响应显式声明编码
浏览器、Postman、第三方 API 不一定发送 UTF-8,响应也不自动带 charset。Hyperf 不会自动补 Content-Type 字符集,需主动控制。
- 接收请求时,用
$request->getParsedBody()前,先检查$request->getHeaderLine('Content-Type')是否含charset=utf-8;若缺失且 body 为 JSON,可预处理:mb_convert_encoding($rawBody, 'UTF-8', 'auto') - 返回响应时,推荐在全局中间件中统一设置:
$response->withHeader('Content-Type', 'application/json; charset=utf-8') - 对 Form 表单提交(
application/x-www-form-urlencoded),确保前端 HTML 有<meta charset="UTF-8">,否则 IE/旧浏览器可能用 GBK 提交
文件读写与第三方 SDK 特别处理
CSV、Excel、日志文件、Redis 存储等场景易被忽略。
- 读取 CSV:用
fopen(..., 'rb')二进制模式打开,再用mb_convert_encoding($line, 'UTF-8', 'GBK')转换(根据来源判断源编码) - 生成 Excel(如 PhpSpreadsheet):创建 Writer 前调用
$spreadsheet->getDefaultStyle()->getFont()->setName('Arial')并确保单元格值已为 UTF-8 字符串 - Redis 存储中文:Swoole Redis 客户端默认原样存储字节,只要写入前是 UTF-8 字符串,读取后无需 decode —— 但若用其他语言客户端写入 GBK,PHP 侧需
mb_convert_encoding($val, 'UTF-8', 'GBK')










