項目歷史原因需從 GBK 遷移至 UTF-8,但 json_encode 僅支持 UTF-8。直接 iconv 序列化字符串會因 default_charset 干擾導致反序列化失敗;遞歸遍歷數組調用 iconv 則性能差、代碼冗長、多維數組易出錯。本文介紹一行代碼核心技巧:eval('return ' . iconv(...) . var_export($arr, true) . ';'),利用 PHP 解析器原生處理任意結構數組,高效、穩健、零依賴。
unserialize(iconv('gbk','utf-8', serialize($arr))) —— 受 ini_set('default_charset') 影響,反序列化常報錯或數據截斷。array_iconv_recursive —— 代碼量大、深層數組棧溢出風險、引用/循環引用處理複雜。iconv 轉編碼 → eval() 執行還原。<?php
/**
* 數組編碼轉換(任意維度、關聯/索引混合、含引用均可)
* @param string $in_charset 源編碼(如 GBK、GB2312)
* @param string $out_charset 目標編碼(如 UTF-8、UTF-8//IGNORE)
* @param array $arr 待轉換數組
* @return array 轉換後數組
*/
function array_iconv(string $in_charset, string $out_charset, array $arr): array {
// 1. var_export($arr, true) 返回合法 PHP 代碼字符串,如 "array ('key' => '值', ...)"
// 2. iconv 轉換字符串編碼
// 3. eval('return ...;') 由 PHP 解析器還原為數組,自動處理所有結構
$code = 'return ' . iconv($in_charset, $out_charset, var_export($arr, true)) . ';';
return eval($code);
}
<?php
// 模擬 GBK 環境下的數組(實際文件編碼為 GBK)
$gbkArr = [
'name' => '測試',
'list' => ['蘋果', '香蕉', ['嵌套' => '深層']],
'id' => 123,
];
// 假設當前腳本為 UTF-8,模擬 GBK 數據輸入
// 實際場景:讀取 GBK 編碼的配置文件、緩存文件、第三方 API 返回
$utf8Arr = array_iconv('GBK', 'UTF-8//IGNORE', $gbkArr);
echo json_encode($utf8Arr, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
/* 輸出:
{
"name": "測試",
"list": ["蘋果", "香蕉", {"嵌套": "深層"}],
"id": 123
}
*/
| 步驟 | 函數 | 作用 | 關鍵點 |
|---|---|---|---|
| 1 | var_export($arr, true) | 輸出數組的「合法 PHP 代碼表示」 | 第二參數 true 返回字符串而非直接輸出;輸出格式為 array (...),可直接被解析器執行 |
| 2 | iconv($in, $out, $str) | 將代碼字符串按字符級轉換編碼 | 只轉換字面量字符串內容,不影響 PHP 語法結構(括號、箭頭、引號均為 ASCII) |
| 3 | eval('return ' . $code . ';') | 由 PHP 內核解析並執行,還原數組 | 利用編譯器原生支持:多維、引用、對象、資源類型(資源類型會丟失) |
var_export 輸出純數據結構無代碼注入風險。**嚴禁對不可信用戶輸入使用**。var_export + iconv + eval 均為 C 級內核函數,百萬級元素數組毫秒級完成,遠快於 PHP 層遞歸。// 遞歸版:代碼冗長、易漏邊界、引用處理麻煩
function array_iconv_recursive(string $in, string $out, array &$arr): void {
foreach ($arr as $key => &$val) {
if (is_array($val)) {
array_iconv_recursive($in, $out, $val);
} elseif (is_string($val)) {
$val = iconv($in, $out, $val);
}
// 忽略整數、浮點、布爾、null、資源、對象...
}
}
| 場景 | 推薦方案 |
|---|---|
| 常規業務數組(<10萬元素) | var_export + iconv + eval(本文方案) |
| 超大數組/流式處理 | 分塊處理或遞歸生成器 |
| 包含對象/資源/閉包 | 序列化法(但對象需實現 __sleep/__wakeup) |
| 不可信數據源 | 遞歸遍歷 + 白名單類型過濾 |
| 長期項目/團隊協作 | 封裝為 ArrayEncoding::convert($arr, 'GBK', 'UTF-8') 統一入口 |
eval('return ' . iconv(...) . var_export($arr, true) . ';') 是 PHP 數組編碼轉換的「核武器級」方案:**利用語言自身解析器處理結構,利用 iconv 處理編碼,一行代碼解決所有維度、類型、引用問題**。理解其原理,能啟發更多「代碼即數據、數據即代碼」的元編程技巧。