laravel迁移需强制utf8mb4编码:建表后用db::statement转换字符集,字段用collation()或addcolumn()指定排序规则,且在appserviceprovider中设schema::defaultstringlength(191)避免索引过长。

在 Laravel 项目中执行数据库迁移时,字段或表默认使用 MySQL 连接的字符集,若未显式干预,新建表可能仍用 utf8(即最多 3 字节的伪 UTF-8),导致 emoji 和中文生僻字存入后变 ??? 或直接报错 SQLSTATE[HY000]: General error: 1366 Incorrect string value;必须在迁移文件中强制指定 utf8mb4 才能确保字段级编码正确。
新建表时强制整表使用 utf8mb4
第一步:在 Schema::create() 闭包结束后,立即追加 DB::statement() 手动转换表字符集。
第二步:调用 DB::statement("ALTER TABLE `posts` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
这一步不可省略——Laravel 9.x 之前版本即使 config/database.php 已设 charset => 'utf8mb4',Schema::create() 生成的建表语句仍默认用 utf8,仅靠配置无法覆盖。
第三步:确保该语句放在 up() 方法末尾,且与 Schema::create() 同处一个事务上下文。若拆到单独 migration 文件里执行,可能因事务隔离导致表锁或执行顺序错乱。
为单个字段指定 utf8mb4 排序规则
方法一:适用于 string()、text()、tinyText() 等支持 collation 的类型
$table->string('title')->collation('utf8mb4_unicode_ci');
注意:【integer()、boolean()、json() 等类型不支持 collation() 方法,调用会静默失败】
方法二:用 raw 表达式绕过 Laravel 构建器限制(兼容所有字段类型)
$table->addColumn('VARCHAR', 'bio', ['length' => 500, 'collation' => 'utf8mb4_bin']);
此写法需引入 use Illuminate\Support\Facades\DB; 并确认底层 PDO 支持该语法;MySQL 5.7.8+ 才完整支持 utf8mb4_bin。
避免索引过长报错的配套操作
执行 php artisan migrate 时若报错 Specified key was too long,说明默认字符串长度 255 超出 utf8mb4 下的索引限制(767 字节)。
在 AppServiceProvider 的 boot() 方法中添加:
Schema::defaultStringLength(191);
这一步必须做——191 × 4 = 764 字节,刚好低于 InnoDB 默认页大小限制;不设会导致 unique 索引或主键创建失败,且错误提示不直观。











