IIS + PHP 環境下,URL 傳遞中文參數(?id=中文)頻繁出現亂碼,根因在於瀏覽器編碼差異、IIS URL Rewrite 模塊編碼固化為 GBK、PHP 內部採用 UTF-8 多重編碼不一致。本文歸納兩類實戰有效方案。
https://site.com/page?id=測試$_GET['id'] 獲得亂碼(如 娴嬭瘯 或 %E6%B5%8B%E8%AF%95 雙重編碼)urlencode + 後端 urldecode(最通用)核心原則:URL 標準僅允許 ASCII,中文必須百分號編碼後傳輸。
<!-- 模板/頁面生成鏈接時 -->
<a href="td.php?id=<?php echo urlencode('中文'); ?>">點擊</a>
<?php
// 接收頁
$id = urldecode($_GET['id']);
// 或 ThinkPHP 封裝
$id = urldecode(I('get.id'));
?>
當無法控制前端(如第三方回調、舊系統跳轉、IIS Rewrite 直接將 GBK 編碼中文放入 URL)時,在入口文件或公共控制器統一轉碼:
<?php
// 入口文件 index.php 或 BaseController::_initialize()
if (!empty($_GET)) {
foreach ($_GET as $key => $val) {
if (is_string($val)) {
// 嘗試從 GBK 轉 UTF-8
$_GET[$key] = mb_convert_encoding($val, 'UTF-8', 'GBK');
// 或 iconv
// $_GET[$key] = iconv('GBK', 'UTF-8//IGNORE', $val);
}
}
}
// 同理處理 $_POST、$_REQUEST
適用場景:
| 環節 | 編碼行為 | 衝突點 |
|---|---|---|
| 瀏覽器發請求 | IE/Edge 按系統編碼(GBK)編碼 URL;Chrome/Firefox 按頁面編碼(UTF-8) | 同一 URL 不同瀏覽器發送的字節流不同 |
| IIS 接收 | 預設按 UTF-8 解碼 URL;Rewrite 模塊內部按 GBK 處理中文 | Rewrite 後的參數已是 GBK 字節流,PHP 當 UTF-8 讀取即亂碼 |
| PHP 獲取 $_GET | 直接拿 IIS 解碼後的字串 | 若 IIS 解碼錯誤,PHP 只能事後修補 |
<meta charset="utf-8">、PHP header('Content-Type: text/html; charset=utf-8')、資料庫 SET NAMES utf8mb4)。urlencode(),封裝為模板函數 {:U('action', ['kw'=>$keyword])}。index.php 最頂部加入方案二代碼,作為安全網。header("Content-Type: text/html; charset=utf-8") 不解決 GET 參數亂碼,它只影響響應體編碼。iconv('GBK','UTF-8',$str) 遇到非法字節會報錯或截斷,建議加 //IGNORE 或用 mb_convert_encoding。enctype="multipart/form-data" 且頁面 UTF-8,通常不亂碼;但 application/x-www-form-urlencoded 同樣受瀏覽器編碼影響,同理處理。徹底解決 IIS 中文亂碼,關鍵在於「源頭編碼統一 + 傳輸強制編碼 + 入口兼容修補」三層防線。