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

PHP 字符串編碼轉換完全指南:mb_convert_encoding、iconv、自定義函數、MySQL 連接編碼

     編輯:PHP 相關知識

核心函數對比

函數擴展依賴特點推薦度
mb_convert_encoding()mbstring (PHP 內置常開啟)支持超多編碼、無 BUG、語法簡潔、性能好⭐⭐⭐⭐⭐ (首選)
iconv()iconv (系統庫,通常內置)標準 POSIX、GBK 轉換有已知 BUG、需 //IGNORE 容錯⭐⭐⭐ (無 mbstring 環境備選)
mb_convert_variables()mbstring批量轉換數組/對象變量⭐⭐⭐⭐

mb_convert_encoding() 標準用法

<?php
// 基本語法:mb_convert_encoding($str, $to_encoding, $from_encoding)
// $from_encoding 可省略,自動檢測(不推薦,不準確)

// 1. GBK → UTF-8 (最常見)
$utf8 = mb_convert_encoding($gbkStr, 'UTF-8', 'GBK');

// 2. UTF-8 → GBK (輸出兼容舊系統)
$gbk = mb_convert_encoding($utf8Str, 'GBK', 'UTF-8');

// 3. 批量轉換數組
$post = mb_convert_variables('UTF-8', 'GBK', $_POST); // 直接修改 $_POST 引用

// 4. 指定多種可能源編碼(自動檢測,較慢)
$utf8 = mb_convert_encoding($str, 'UTF-8', 'UTF-8, GBK, ISO-8859-1');
?>

iconv() 避坑指南:GBK //IGNORE

已知 BUG:iconv 處理 GBK/GB2312 時,遇到某些字符(如 — U+2014 全角破折號、• 圓點號)會中斷轉換並返回 false/空字符串,且後續字符全部丟失。

<?php
// ❌ 錯誤:遇到問題字符直接失敗
$gbk = iconv('UTF-8', 'GBK', $utf8Str);

// ✅ 正確:添加 //IGNORE 忽略無法轉換字符
$gbk = iconv('UTF-8', 'GBK//IGNORE', $utf8Str);
// 或 //TRANSLIT 嘗試近似字符替換
$gbk = iconv('UTF-8', 'GBK//TRANSLIT', $utf8Str);

// 反向同理
$utf8 = iconv('GBK', 'UTF-8//IGNORE', $gbkStr);
?>

自動檢測並轉換為 UTF-8 通用函數

<?php
/**
 * 智能轉碼:自動檢測編碼並轉為 UTF-8
 * @param mixed $data 字符串、數組、對象
 * @return mixed 轉換後的數據
 */
function toUtf8($data) {
    if (is_string($data)) {
        // 嚴格模式檢測
        $encoding = mb_detect_encoding($data, ['UTF-8', 'GBK', 'GB2312', 'ISO-8859-1', 'ASCII'], true);
        if ($encoding && $encoding !== 'UTF-8') {
            return mb_convert_encoding($data, 'UTF-8', $encoding);
        }
        return $data; // 已是 UTF-8 或無法檢測
    } elseif (is_array($data)) {
        foreach ($data as $key => $value) {
            $data[$key] = toUtf8($value);
        }
        return $data;
    } elseif (is_object($data)) {
        foreach ($data as $key => $value) {
            $data->$key = toUtf8($value);
        }
        return $data;
    }
    return $data;
}

// 入口統一處理
$_GET = toUtf8($_GET);
$_POST = toUtf8($_POST);
$_REQUEST = toUtf8($_REQUEST);
?>

MySQL 連接編碼:三句真言

<?php
// PDO (推薦)
$pdo = new PDO(
    "mysql:host=localhost;dbname=test;charset=utf8mb4",
    'user', 'pass',
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci"
    ]
);

// mysqli
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$mysqli->set_charset('utf8mb4'); // 必須調用!構造函數 charset 參數不可靠

// 等效原始 SQL(理解原理)
/*
SET NAMES utf8mb4;                    -- 設置客戶端/連接/結果集編碼
SET CHARACTER SET utf8mb4;            -- 同 SET NAMES
SET COLLATION_CONNECTION = 'utf8mb4_unicode_ci'; -- 設置排序規則
*/
?>

MySQL 服務端配置(my.cnf / my.ini)

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'
skip-character-set-client-handshake = 1  # 強制忽略客戶端編碼請求,統一服務端設置

編碼轉換常見誤區

  1. 雙重轉碼:數據已是 UTF-8,又執行 mb_convert_encoding($str, 'UTF-8', 'GBK') → 亂碼。必須先檢測。
  2. 依賴 mb_detect_encoding 非嚴格模式:mb_detect_encoding($str, 'UTF-8, GBK') 會按順序猜測,純 ASCII 字符串會被誤判為第一個編碼。必須第三參數 true 啟用嚴格模式。
  3. 忽略 //IGNORE 導致數據截斷:iconv 轉 GBK 遇特殊字符直接截斷,數據悄悄丟失。
  4. 數據庫連接編碼與表編碼不一致:連接 UTF-8,表 GBK → 存入亂碼。連接、表、欄、服務端全鏈路統一 utf8mb4。
  5. PHP 文件編碼非 UTF-8 無 BOM:源碼中文變為未知字節,轉碼無從談起。編輯器強制保存為 UTF-8 無 BOM。

性能建議

  • 高頻熱點路徑:優先 mb_convert_encoding,避免 iconv 系統調用開銷。
  • 批量轉換:mb_convert_variables('UTF-8', 'GBK', $_POST) 一次性處理超全局變量。
  • 入口統一轉碼:在框架入口/公共文件處理 $_GET/POST/REQUEST,業務代碼假設輸入已是 UTF-8,不再重複轉碼。

總結

  1. 首選 mb_convert_encoding:功能全、無 BUG、性能好。
  2. 次選 iconv(...//IGNORE):無 mbstring 環境下的備選,必加 //IGNORE。
  3. MySQL 全鏈路 utf8mb4:服務端、連接、表、欄統一,三句真言 SET NAMES utf8mb4 等。
  4. 入口統一轉碼:toUtf8($_POST) 等,業務層零編碼邏輯。
  5. 源碼 UTF-8 無 BOM:編碼問題 90% 源於文件保存編碼錯誤。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved