首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 處理 Emoji 表情三大方案:utf8mb4、Base64 編碼、過濾移除完整比較

     編輯:PHP 綜合知識

微信開發中儲存暱稱常遇 Emoji 導致 MySQL utf8 (3 位元組) 寫入失敗、欄位變空字串。本文對比三種解決方案優劣、適用場景與實作程式碼,助你依專案條件做最佳選擇。

根本原因

  • MySQL utf8 (實為 utf8mb3) 僅支援 BMP 平面字符 (3 位元組)。
  • Emoji 屬於補充平面,需 4 位元組編碼 (utf8mb4)。
  • 插入 4 位元組字符到 utf8 欄位會導致截斷或整欄位清空 (視 SQL 模式而定)。

方案比較總覽

方案優點缺點適用場景
1. 升級 utf8mb4 徹底解決、相容現有 utf8、無需程式碼改動、效能損耗極微 需 MySQL 5.5.3+、資料庫/表/欄位/連線全鏈路修改 ✅ 首選方案、新專案、可控制資料庫版本
2. Base64 編碼存儲 不改資料庫編碼、任意二進位資料可存、相容舊系統 空間膨脹 33%、不可直接 LIKE 查詢/排序、讀寫需編解碼 無法升級資料庫、舊專案快速修復、需儲存二進位
3. 過濾移除 Emoji 零資料庫變更、零儲存空間增加、前端顯示無相容問題 資料遺失、用戶體驗下降、正則效能需注意 Emoji 非核心業務、嚴格合規要求、極度舊環境

方案一:升級 utf8mb4 (推薦)

-- 1. 資料庫層級
ALTER DATABASE `db_name` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

-- 2. 資料表層級
ALTER TABLE `table_name` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 3. 欄位層級 (若表轉換未完全)
ALTER TABLE `table_name` CHANGE `col_name` `col_name` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 4. 連線層級 (PHP PDO)
$pdo = new PDO("mysql:host=...;dbname=...;charset=utf8mb4", $user, $pass);
$pdo->exec("SET NAMES utf8mb4");

注意:utf8mb4 索引鍵長度限制 191 字元 (InnoDB 767 bytes / 4),原 VARCHAR(255) 需縮減或啟用 innodb_large_prefix=ON (MySQL 5.7.7+ 預設開啟)。

方案二:Base64 編碼存儲

// 寫入前
$nickname = base64_encode($rawNickname); // Emoji 變成 ASCII 安全字串
$stmt->bindValue(':nick', $nickname);

// 讀取後
$rawNickname = base64_decode($row['nickname']);
  • 適用 utf8/latin1 任何編碼欄位。
  • 查詢需 WHERE base64_decode(nick) LIKE ... 效能極差,建議另建搜尋欄位 (如拼音首字母)。

方案三:過濾移除 Emoji (PHP 7.1+)

function filterEmoji(string $str): string {
    // 使用 Grapheme Cluster 邊界正確分割,避免拆破組合字符
    $graphemes = grapheme_str_split($str); // PHP 7.4+ 需 intl 擴展
    // 兼容寫法:preg_match_all('/\X/u', $str, $m); $graphemes = $m[0];
    
    $filtered = array_filter($graphemes, function($ch) {
        // 過濾 4 位元組 UTF-8 字符 (Emoji 多為 4 字節)
        // 更精確:檢查 Unicode 範圍 U+1F300–U+1FAFF 等 Emoji 區塊
        return strlen($ch) < 4; 
    });
    return implode('', $filtered);
}

// 使用範例
$clean = filterEmoji("Hello 😀 World 👍"); // "Hello  World "

進階正則 (精確匹配 Emoji 區塊,需 PHP 7.3+ /u 模式):

$str = preg_replace('/[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}]/u', '', $str);

前端顯示補充

  • iOS 原生支援 Emoji 彩色渲染。
  • Android / Windows 需引入 Emoji 字體 (如 Noto Color Emoji) 或前端庫 (Twemoji, EmojiOne) 將 Emoji 替換為 <img>。
  • 資料庫存 utf8mb4 並不保證前端完美顯示,仍需前端配合。

決策建議流程

  1. MySQL ≥ 5.5.3 且可控制資料庫 → 直接升級 utf8mb4 (最省事、最完整)。
  2. 無法升級資料庫、但可改程式碼 → Base64 編碼 (快速修復,注意查詢限制)。
  3. 極度受限環境、Emoji 非必要 → 過濾移除 (最後手段)。

相關專題:《PHP 字串用法總結》、《PHP 常見資料庫操作技巧匯總》。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved