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

PHP array_walk_recursive 深度應用:遞迴處理多維陣列的實戰技巧

     編輯:PHP 綜合知識

array_walk_recursive() 是 PHP 陣列操作的利器,能遞迴遍歷多維陣列的每個「葉子節點」(非陣列值),對每個值執行回呼函式。不同於 array_walk() 僅處理第一層,它自動深入巢狀結構,極適合資料清洗、編碼轉換、XSS 過濾、敏感字遮罩等場景。

函式簽名與參數詳解

array_walk_recursive(array &$array, callable $callback, mixed $userdata = null): bool
參數說明
&$array輸入陣列,傳址呼叫,回呼中修改值會直接影響原陣列
$callback回呼函式,簽名 func(mixed $value, string|int $key, mixed $userdata)。若需修改原值,第一參數必須加 &:func(&$value, $key)
$userdata可選,傳遞額外資料給回呼(如配置選項、服務物件)

實戰範例

1. 全站輸出前 XSS 過濾(HTML 實體化)

function htmlEscapeRecursive(array &$data): void {
    array_walk_recursive($data, function(&$value, $key) {
        if (is_string($value)) {
            $value = htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
        }
    });
}

// 使用
$data = [
    'title' => '',
    'user' => ['name' => 'Tom', 'bio' => ['desc' => 'hello & world']]
];
htmlEscapeRecursive($data);
// 結果:所有字串值已轉義,結構保持不變

2. 陣列編碼統一轉換(UTF-8 → GBK 匯出)

function convertEncodingRecursive(array &$data, string $from, string $to): void {
    array_walk_recursive($data, function(&$value, $key) use ($from, $to) {
        if (is_string($value)) {
            $value = mb_convert_encoding($value, $to, $from);
        }
    });
}

3. 敏感資料遮罩(手機、身分證、Email)

function maskSensitiveRecursive(array &$data): void {
    $patterns = [
        '/(\d{3})\d{4}(\d{4})/' => '$1****$2',      // 手機
        '/(\w{1,3})[\w.-]*@/' => '$1***@',           // Email 前綴
        '/(\d{6})\d{8}(\d{4})/' => '$1********$2',   // 身分證
    ];

    array_walk_recursive($data, function(&$value, $key) use ($patterns) {
        if (is_string($value)) {
            foreach ($patterns as $pattern => $replacement) {
                $value = preg_replace($pattern, $replacement, $value);
            }
        }
    });
}

4. 攜帶額外參數:動態配置過濾規則

function trimStringsRecursive(array &$data, array $options = []): void {
    $charset = $options['charset'] ?? 'UTF-8';
    $skipKeys = $options['skip_keys'] ?? [];

    array_walk_recursive($data, function(&$value, $key) use ($charset, $skipKeys) {
        if (in_array($key, $skipKeys, true)) return;
        if (is_string($value)) {
            $value = trim($value);
            // 可選:移除控制字元
            $value = preg_replace('/[\x00-\x1F\x7F]/', '', $value);
        }
    });
}

// 使用
trimStringsRecursive($input, ['skip_keys' => ['password', 'token']]);

常見誤區與避坑指南

誤區正確認知
以為會遍歷陣列鍵名只遍歷「非陣列值」(葉子節點),中間層陣列不會觸發回呼
回呼未用 &$value 導致原陣列未修改必須傳址 function(&$value) 才能修改原陣列
試圖在回呼中刪除元素 unset($array[$key])無效,$key 是葉子鍵名,且陣列在內部迭代中,刪除會導致未定義行為
處理巨大陣列導致記憶體/遞迴深度溢出PHP 遞迴深度受限於 xdebug.max_nesting_level (預設 256),超深結構改用迭代器 RecursiveArrayIterator

效能比較

// 10 萬筆扁平陣列
$data = array_fill(0, 100000, ['a' => 'x', 'b' => ['c' => 'y']]);

// array_walk_recursive:約 45ms
// 手寫遞迴 foreach:約 38ms (較快,但程式碼冗長)
// RecursiveIteratorIterator:約 52ms (物件開銷大)

// 結論:中小型陣列用 array_walk_recursive 開發效率最高;極大/極深陣列考慮 Generator + 迭代器串流處理

進階替代方案

  • RecursiveArrayIterator + RecursiveCallbackFilterIterator:可過濾、轉換、限制深度,物件導風格。
  • array_walk_recursive + Generator:配合 yield 實現延遲處理,適合串流管線。
  • symfony/polyfill-php80:PHP 8.1+ 內建 array_is_list()、array_find() 等新函式,配合使用更強大。

善用 array_walk_recursive(),能以極少程式碼完成多維陣列的統一轉換與清洗。記住「傳址修改、僅葉子節點、避免深度溢出」三原則,即可安全高效地應用於專案中。

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