答案是必须同步配置Laravel连接层、MySQL服务端、数据库、表及字段字符集为utf8mb4,并在Laravel中设置Schema::defaultStringLength(191)以避免索引超长错误。

你在Laravel里往数据库存笑脸❓、爱心❤️或握手?这类Emoji时,直接报错SQLSTATE[HY000]: General error: 1366 Incorrect string value,不是代码写错了,也不是PHP版本问题,而是MySQL根本没准备好接收4字节UTF-8字符。
先确认是不是真被utf8mb3卡住了
登录MySQL执行:SHOW VARIABLES LIKE 'character_set%';
重点看character_set_client、character_set_connection、character_set_database这三项——如果全是utf8(注意:不是utf8mb4),那就坐实了:你用的是MySQL的“伪UTF-8”,它只认最多3字节的字符,而Emoji普遍占4字节。
【utf8在MySQL里实际叫utf8mb3,这是历史包袱,不是标准UTF-8】
改Laravel配置:光改数据库没用,连接层必须同步
打开config/database.php,找到mysql配置块,在里面补全三项:
'charset' => 'utf8mb4'
'collation' => 'utf8mb4_unicode_ci'
'options' => [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci"]
这一步漏掉options,Laravel 8+在某些PDO驱动下仍会走默认utf8连接,存Emoji照样失败。
改MySQL服务端配置:不重启等于白改
编辑my.cnf(Linux)或my.ini(Windows),在[mysqld]段下加入:
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
保存后必须执行sudo systemctl restart mysql(或对应重启命令),否则SHOW VARIABLES看到的还是旧值。
改表结构:三步不能跳,顺序不能乱
第一步:升级数据库字符集ALTER DATABASE your_db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
第二步:升级表字符集ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
第三步:单独处理带索引的VARCHAR字段
如果字段是VARCHAR(255)且建了唯一索引,必须先缩成VARCHAR(191)——因为utf8mb4下每个字符最多占4字节,255×4=1020字节,超过InnoDB单列索引767字节上限;【不缩长度就执行MODIFY,会直接报错1071】ALTER TABLE your_table MODIFY your_column VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Laravel迁移时防坑:默认长度要重设
在app/Providers/AppServiceProvider.php的boot()方法里加一行:
Schema::defaultStringLength(191);
否则新生成的迁移文件里$table->string('email')会默认建VARCHAR(255),建索引时立刻触发Specified key was too long错误。


















