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

解決 PHP 讀取 MSSQL 2008 資料輸出 JSON 時中文亂碼問題

     編輯:PHP 相關知識

問題背景

專案環境:PHP 檔案與網頁均為 UTF-8 編碼,資料庫為 SQL Server 2008 預設編碼(Code Page 936,即 GBK)。直接使用 json_encode() 輸出查詢結果時,中文欄位顯示為空或亂碼。

核心解決方案

採用「查詢語句轉碼 + 資料陣列遞迴轉碼」雙重保障:

  1. SQL 查詢語句:從 UTF-8 轉為 GBK 再送入 sqlsrv_query()。
  2. 結果集處理:將每筆資料的每個欄位從 GBK 轉為 UTF-8,再經 urlencode → json_encode → urldecode 三步走,繞過 json_encode 對中文 Unicode 轉義的限制。

完整實作程式碼

1. 主查詢腳本 employeeGet.php

<?php
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-cache');

require '../conn.php';
require '../share/json_gbk2utf8.php';

// 日期欄位轉字串避免毫秒顯示問題
$query = 'SELECT seq, employeeID, employeeName, department, position, sex, birthday, entryTime, description,
          CONVERT(varchar(20), createTime, 120) AS createTime,
          CONVERT(varchar(20), updateTime, 120) AS updateTime
          FROM employees';

// 查詢語句轉 GBK
$query = iconv('UTF-8', 'GBK//IGNORE', $query);

$arr = [];
if ($result = sqlsrv_query($conn, $query)) {
    while ($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
        $arr[] = $row;
    }
}

// 使用自訂 JSON 函數輸出
echo JSON($arr);
?>

2. 核心轉碼類別 json_gbk2utf8.php

<?php
/**
 * 遞迴處理陣列,對每個值執行指定函數
 * @param array &$array  目標陣列(引用)
 * @param callable $function  處理函數
 * @param bool $applyToKeys  是否同時處理鍵名
 */
function arrayRecursive(array &$array, callable $function, bool $applyToKeys = false): void {
    static $depth = 0;
    if (++$depth > 1000) {
        die('Possible deep recursion attack');
    }

    foreach ($array as $key => &$value) {
        if (is_array($value)) {
            arrayRecursive($value, $function, $applyToKeys);
        } else {
            // GBK → UTF-8
            $value = iconv('GBK//IGNORE', 'UTF-8', $value);
            // 執行使用者函數(如 urlencode)
            $value = $function($value);
            $array[$key] = $value;
        }

        if ($applyToKeys && is_string($key)) {
            $newKey = $function($key);
            if ($newKey !== $key) {
                $array[$newKey] = $array[$key];
                unset($array[$key]);
            }
        }
    }
    $depth--;
}

/**
 * 將陣列安全轉為 JSON 字串(支援中文)
 * @param array $array
 * @return string
 */
function JSON(array $array): string {
    arrayRecursive($array, 'urlencode', true);
    $json = json_encode($array);
    return urldecode($json);
}
?>

3. 寫入資料時的編碼處理

新增/更新 SQL 語句同樣需轉碼:

$query = "INSERT INTO employees (employeeID, employeeName, department) VALUES (N'{$employeeID}', N'{$employeeName}', N'{$department}')";
// 或 UPDATE ...
$query = iconv('UTF-8', 'GBK//IGNORE', $query); // 關鍵步驟
sqlsrv_query($conn, $query);

關鍵技術點說明

  • N'字串':T-SQL 前綴 N 表示 Unicode 字串常值,配合 GBK 查詢語句可正確寫入中文。
  • iconv('GBK//IGNORE', 'UTF-8', ...)://IGNORE 參數可跳過無法轉換的字元,避免中斷。
  • urlencode → json_encode → urldecode:利用 URL 編碼將中文轉為 ASCII 安全字元,繞過 json_encode 的 Unicode 轉義,最後還原。
  • 遞迴深度限制 1000 層,防止惡意資料導致堆疊溢位。

現代替代方案(PHP 5.4+)

若環境允許,建議直接使用 json_encode($data, JSON_UNESCAPED_UNICODE),並確保資料庫連線與 PHP 內部編碼皆為 UTF-8(sqlsrv_connect 設定 CharacterSet => 'UTF-8'),可徹底省去手動轉碼麻煩。

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