Laravel连接MariaDB时中文、emoji乱码或报错1366,根本原因是服务端未启用utf8mb4;需先配置MariaDB服务端字符集为utf8mb4并重启,再修改Laravel的database.php配置charset、collation及PDO初始化命令,最后升级现有表与字段字符集,并在迁移中显式声明utf8mb4。

在 Laravel 项目中连接 MariaDB 时,中文、emoji 或生僻字存入数据库变成 ??? 或直接报错 SQLSTATE[HY000]: General error: 1366 Incorrect string value,根本原因是 MySQL/MariaDB 连接层仍用旧式 utf8(即最多 3 字节的伪 UTF-8),而 Laravel 默认配置未强制覆盖该层。
确认 MariaDB 服务端已启用 utf8mb4
这一步不做,后续所有 Laravel 配置都无效。登录 MariaDB 命令行执行:SHOW VARIABLES LIKE 'character_set%';,检查 【character_set_server】 和 【character_set_database】 是否均为 utf8mb4。若不是,编辑 /etc/my.cnf(Linux)或 my.ini(Windows),在 [mysqld] 段下添加:
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init-connect = 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'
改完必须重启 MariaDB 服务,否则配置不生效。
修改 Laravel 数据库连接配置
只改 .env 文件里的 DB_CHARSET=utf8mb4 是无效的——Laravel 官方源码根本没读这个变量。
打开 config/database.php,定位到 'mysql' 配置块,在其中加入三项:
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'options' => [
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci"
]
注意:PDO::MYSQL_ATTR_INIT_COMMAND 这一行不能省,Laravel 8+ 在某些 PDO 版本下不加它,连接仍走默认 utf8。
升级已有表与字段的字符集
即使连接和配置全对了,老表老字段还是 latin1 或 utf8,数据一写就丢。
第一步:对数据库执行ALTER DATABASE your_db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
第二步:逐个转换表(替换 your_table_name):ALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
第三步:如果某列需特殊排序规则(如大小写敏感搜索),单独改列:ALTER TABLE users MODIFY nickname VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
迁移文件中显式声明字符集
Laravel 的 Schema::create() 在 9.x 之前默认建表用 utf8,哪怕你改了 config 也不生效。
方法一:在迁移文件里追加语句(推荐用于已有项目)
在 up() 方法末尾加:DB::statement("ALTER TABLE posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
方法二:新建迁移时直接指定字段 collation(5.8+ 支持)$table->string('title')->collation('utf8mb4_unicode_ci');
注意:整数、布尔等类型不支持 collation 参数,加了会报错。
清空权限缓存避免 can() 失效
如果你同时用了 spatie/laravel-permission,角色权限分配后 $user->can('edit') 返回 false,大概率是缓存没更新。
执行:php artisan cache:forget spatie.permission.cache
这一步必须做,否则新分配的权限永远不生效。


















