生产环境laravel数据库必须统一使用utf8mb4字符集,需在建库、连接、迁移三环节强制指定:建库执行create database语句并验证;.env中配置db_charset和db_collation;database.php中设置charset、collation及pdo初始化命令;迁移前用tinker批量转换表结构并调整字段长度。

生产环境Laravel数据库字符集配置错误会导致中文乱码、emoji存储失败、JSON字段解析异常,甚至引发数据截断或迁移中断。必须在建库、连接、迁移三个环节统一强制指定utf8mb4,不能依赖MySQL默认值。
建库时显式指定字符集与排序规则
登录MySQL命令行或管理工具(如phpMyAdmin、DBeaver),执行以下语句创建数据库:
CREATE DATABASE `your_db_name` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
【必须用utf8mb4,不是utf8】 MySQL的utf8是阉割版,仅支持3字节字符;utf8mb4才完整支持4字节emoji和生僻汉字。若此处用错,后续所有配置都无效。
确认建库成功后,运行 SHOW CREATE DATABASE your_db_name; 检查输出中明确包含 CHARACTER SET utf8mb4 和 COLLATE utf8mb4_unicode_ci。
配置.env文件中的连接参数
编辑项目根目录下的 .env 文件,确保以下三项同时存在且匹配:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_db_name
DB_USERNAME=root
DB_PASSWORD=your_password
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
DB_PREFIX=(可选,但建议留空或设为小写字母+下划线)
这四行(DB_CHARSET、DB_COLLATION、DB_PREFIX、DB_CONNECTION)缺一不可——Laravel 13.2.0 默认不读取 DB_CHARSET/DB_COLLATION,但 config/database.php 中 mysql 连接器会主动识别并注入 PDO DSN 的 charset 参数。漏掉 DB_CHARSET 将导致PDO连接仍用 latin1。
修改config/database.php适配utf8mb4
打开 config/database.php,在 'mysql' 连接配置数组中,找到 'options' 键,确保包含 PDO::MYSQL_ATTR_INIT_COMMAND:
'options'=> [
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci",
PDO::ATTR_EMULATE_PREPARES => false,
],
这行 INIT_COMMAND 是硬性保障:它在每次PDO连接建立后立即执行,覆盖服务器全局变量设置。没有它,某些云数据库(如阿里云RDS)因权限限制无法通过 my.cnf 修改全局 charset,就会退回到 latin1。
同时检查 'charset' 和 'collation' 字段是否已显式赋值:
'charset'=>'utf8mb4',
'collation'=>'utf8mb4_unicode_ci',
这两个字段必须与 .env 中的 DB_CHARSET/DB_COLLATION 完全一致,大小写敏感。
迁移前校验与强制重置表结构
第一步:执行 php artisan migrate:status,确认所有迁移状态为 Ran。若存在未执行项,先完成迁移。
第二步:运行以下命令批量修正已有表的字符集:
php artisan tinker
→ DB::statement("ALTER DATABASE `your_db_name` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci");
→ foreach (DB::select("SHOW TABLES") as $table) { DB::statement("ALTER TABLE `" . array_values($table)[0] . "` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); }
第三步:针对每个表的TEXT、VARCHAR字段,单独执行MODIFY以扩大长度(因utf8mb4需更多存储空间):
DB::statement("ALTER TABLE users MODIFY name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
⚠️ 注意:此操作不可逆,执行前务必备份整库。VARCHAR(191) 是历史兼容阈值,新表建议直接设为 VARCHAR(255),但需确认MySQL版本 ≥ 5.7.7 或 MariaDB ≥ 10.2.1,否则索引长度超限会报错。











