laravel项目必须统一配置utf8mb4字符集以避免中文乱码、emoji存储失败等问题,需在mysql服务端、laravel配置、ci/cd流水线、迁移文件及存量表中全流程固化验证与设置。

在 Laravel 项目中,数据库字符集配置错误会导致中文乱码、emoji 存储失败、迁移报错或测试环境与生产环境行为不一致,必须在 CI/CD 流水线启动前就固化为自动化检查项。
确认 MySQL 服务端默认字符集
登录目标服务器,执行:mysql -u root -p -e "SHOW VARIABLES LIKE 'character_set%';"
重点检查 【character_set_server】 和 【collation_server】 是否为 utf8mb4 与 utf8mb4_unicode_ci;若非此值,后续所有 Laravel 迁移和 Seeder 都可能 silently 失败。
这一步不可跳过——即使 .env 中设置了 DB_CHARSET=utf8mb4,若 MySQL 服务端未启用 utf8mb4,Laravel 仍会创建 latin1 表结构。
强制 Laravel 迁移使用 utf8mb4
在 config/database.php 的 mysql 连接配置中,显式追加以下键值:
'charset' => 'utf8mb4',<br>'collation' => 'utf8mb4_unicode_ci',<br>'engine' => null,
同时确保 APP_ENV=testing 环境下该配置也被加载——CI 流水线中的测试数据库必须与生产表结构完全一致,否则 php artisan migrate 在 GitHub Actions 中会创建错误编码的表。
CI 流水线中注入字符集验证步骤
在 .github/workflows/ci.yml 的测试 job 中,插入预检步骤:
第一步:启动 MySQL 容器并设置服务端字符集
services:<br> mysql:<br> image: mysql:8.0<br> env:<br> MYSQL_ROOT_PASSWORD: password<br> ports:<br> - 3306:3306<br> options: >-<br> --character-set-server=utf8mb4<br> --collation-server=utf8mb4_unicode_ci
第二步:添加验证脚本,在 composer install 后立即运行
run: |<br> echo "Checking MySQL charset..."<br> mysql -h 127.0.0.1 -P 3306 -u root -ppassword -e "SHOW VARIABLES LIKE 'character_set_server';" | grep -q "utf8mb4" || (echo "❌ MySQL server charset is NOT utf8mb4"; exit 1)
这一步失败将中断整个流水线——宁可构建失败,也不能让带 latin1 表的代码流入测试环境。
模块化项目中按需启用 utf8mb4 表选项
使用 laravel-modules 的项目,需确保每个模块的迁移文件显式声明引擎与字符集:
方法一:在迁移文件 up() 方法中添加
Schema::create('module_posts', function (Blueprint $table) {<br> $table->id();<br> $table->string('title');<br> $table->timestamps();<br> $table->engine = 'InnoDB';<br> $table->charset = 'utf8mb4';<br> $table->collation = 'utf8mb4_unicode_ci';<br>});
方法二:全局覆盖(仅限新项目)——在 app/Providers/AppServiceProvider.php 的 boot() 中写入:
Blueprint::defaultEngine('InnoDB');<br>Blueprint::defaultCharset('utf8mb4');<br>Blueprint::defaultCollation('utf8mb4_unicode_ci');
注意:【此覆盖对已存在的迁移文件无效,仅影响后续新生成的迁移】。
部署阶段同步修正存量表字符集
对于已有生产库但字符集不合规的情况,在 deploy.yml 中插入安全转换步骤:
run: |<br> php artisan tinker --execute="<br> \DB::statement('ALTER DATABASE `homestead` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci');<br> foreach (\DB::select('SHOW TABLES') as \$table) {<br> \$name = array_values((array)\$table)[0];<br> \DB::statement(\"ALTER TABLE `\$name` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci\");<br> }<br> "
该命令仅在 APP_ENV=production 且 DB_DATABASE 明确时执行,避免误操作测试库。











