You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中解决utf8mb3转utf8mb4排序规则转换错误方案

问题与解决方案

问题详情

表结构

1   id  bigint(20) unsigned NULL    NULL    NO  NULL    auto_increment      
2   viewed  tinyint(1)  NULL    NULL    NO  1           
3   type    varchar(191)    utf8    utf8_unicode_ci YES NULL            
4   url longtext    utf8    utf8_unicode_ci YES NULL            
5   p_id    varchar(191)    utf8    utf8_unicode_ci NO  NULL            
6   client_id   varchar(191)    utf8    utf8_unicode_ci NO  NULL        clients(id) 
7   created_at  timestamp   NULL    NULL    YES NULL            
8   updated_at  timestamp   NULL    NULL    YES NULL            

插入数据代码

// 向浏览日志表添加记录
DB::table('client_p_views_log_30days')->insert([
    'client_id'     => $client_id,
    'p_id'          => $p_id,
    'type'          => $type,
    'url'           => $landing_page,
    'created_at'    => now()->toDateTimeString(),
    'updated_at'    => now()->toDateTimeString()
]);

数据库配置(Laravel database.php)

'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),

报错信息

[2024-02-07 12:07:12] production.ERROR: PoptinAPI->newViewsCount()->Exception {
    "client_id": "3dae67a03936e",
    "p_id": "5486bde1f0d03",
    "Exception": "SQLSTATE[HY000]: General error: 3988 Conversion from collation utf8mb3_unicode_ci into utf8mb4_unicode_ci impossible for parameter (SQL: insert into `client_p_views_log_30days` (`client_id`, `p_id`, `type`, `url`, `created_at`, `updated_at`) values (hfafafhah, agadfsgag, desktop, https://test.com/💉-testfoo/, 2024-02-07 12:07:12, 2024-02-07 12:07:12))"
} []

已尝试的无效方法

使用mb_convert_encoding转换URL编码:

'url' => mb_convert_encoding($landing_page, 'UTF-8', 'HTML-ENTITIES'),

结果emoji被破坏为https://test.com/ð-testfoo/,无法还原。


解决步骤

1. 升级表和列的字符集到utf8mb4

MySQL中的utf8是utf8mb3的别名,仅支持3字节字符,无法存储4字节的emoji。必须把表和相关列的字符集改为utf8mb4,排序规则匹配为utf8mb4_unicode_ci:

执行以下SQL:

-- 整体转换表的字符集和排序规则(优先使用这个)
ALTER TABLE client_p_views_log_30days CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 如果上述语句未完全生效,单独修改各列
ALTER TABLE client_p_views_log_30days MODIFY type varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE client_p_views_log_30days MODIFY url longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE client_p_views_log_30days MODIFY p_id varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE client_p_views_log_30days MODIFY client_id varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

2. 确认数据库连接配置一致性

检查.env文件中的DB_CHARSET和DB_COLLATION是否设置为:

DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci

确保Laravel连接数据库时使用的字符集与表/列一致,避免转换冲突。

3. 移除错误的编码转换代码

直接使用原始的$landing_page值插入即可,无需额外编码转换,字符集配置正确后emoji会被正常存储。

4. 验证MySQL全局字符集设置(可选)

检查MySQL实例的全局字符集配置,避免库级别的字符集不匹配:

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

确保character_set_database和collation_database的值为utf8mb4和utf8mb4_unicode_ci。


内容的提问来源于stack exchange,提问作者Rohan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:45:57