PHPのarray_walk_recursive関数の使い方!多次元配列を再帰的に処理する

PHPのarray_walk_recursive関数は、多次元配列のすべてのスカラ値に対して、ユーザー定義の関数を再帰的に適用できる便利な関数です。
文字列の変換や数値への加工など、一括処理したい場合に役立ちます。

array_walk関数が一次元配列にしか適用できないのに対し、array_walk_recursive関数は配列の深さに関わらずすべての要素にアクセスできます。
この記事では、array_walk_recursive関数の基本的な使い方、引数、戻り値、参照渡しによる要素の変更、ユーザーデータの渡し方、そして使用する際の注意点について解説します。

array_walk_recursive関数の基本的な構文

array_walk_recursive 関数の基本的な構文は以下の通りです。

array_walk_recursive(array &$array, callable $callback, mixed $userdata = null): bool
  • $array: 処理対象となる配列です。この配列は参照渡し(& 記号)できるため、コールバック関数内で要素を変更すると元の配列が直接変更される可能性があります。
  • $callback: 各配列要素に適用するコールバック関数です。このコールバック関数は、以下の引数を受け取ります。
    1. $value: 現在処理中の配列要素の値。
    2. $key: 現在処理中の配列要素のキー。
    3. $userdata: オプション。array_walk_recursive の第3引数で渡されたユーザーデータ。
  • $userdata: オプション。$callback 関数の第3引数に渡したい任意のデータです。

array_walk_recursive関数の戻り値

処理が成功した場合は true、失敗した場合は false が返されます。

array_walk_recursive関数を使ってみる

実際にarray_walk_recursive関数を使って、動作を確認しています。

例1:多次元配列のすべての要素を表示する

多次元配列のすべての要素を取得します。

<?php
$data = [
    'fruit' => 'apple',
    'colors' => ['red', 'green', 'blue'],
    'details' => [
        'size' => 'large',
        'weight' => 1.5,
        'origin' => 'Japan'
    ],
    'empty' => [] // 空の配列はスキップされる
];

echo "--- 全ての要素とキーを表示 ---" . PHP_EOL;
array_walk_recursive($data, function($value, $key) {
    echo "キー: {$key}, 値: {$value}" . PHP_EOL;
});
// 出力:
// キー: fruit, 値: apple
// キー: 0, 値: red
// キー: 1, 値: green
// キー: 2, 値: blue
// キー: size, 値: large
// キー: weight, 値: 1.5
// キー: origin, 値: Japan
?>

多次元な$data配列を作成して、array_walk_recursive関数で処理しています。
$valueに配列の値が入って、$keyに配列のキーが入ります。

配列の値($value)が配列の場合にはキーは返ってこない(上記のコードではcolorsdetails)ので、注意が必要です。
また、空の配列emptyは、それ自体は要素を持たないため、コールバック関数は呼び出されません。

例2:多次元配列のすべての文字列を大文字に変換する (元の配列を変更)

コールバック関数の第1引数を参照渡し (&) にすることで、元の配列の要素を直接変更できます。

<?php
$config = [
    'app' => [
        'name' => 'My App',
        'version' => '1.0.0',
        'env' => 'development'
    ],
    'user_settings' => [
        'theme' => 'dark',
        'language' => 'en'
    ],
    'debug_mode' => true
];

echo "--- 変換前 ---" . PHP_EOL;
print_r($config);

array_walk_recursive($config, function(&$value, $key) {
    if (is_string($value)) { // 文字列の場合のみ変換
        $value = strtoupper($value);
    }
});

echo "--- 変換後 (すべて大文字) ---" . PHP_EOL;
print_r($config);
// 出力例:
// --- 変換前 ---
// Array ( ... )
// --- 変換後 (すべて大文字) ---
// Array
// (
//     [app] => Array ( [name] => MY APP [version] => 1.0.0 [env] => DEVELOPMENT )
//     [user_settings] => Array ( [theme] => DARK [language] => EN )
//     [debug_mode] => 1
// )
?>

アプリケーションの定義のような$config配列の値を変更しています。
&$value」に配列の値が、参照渡しで渡されます。これで$valueを変更すると、元の配列の値が上書きされます。

$valueの値をstrtoupper関数で大文字にして、上書きしています。
出力すると、値が大文字になっていることが確認できました。

true1に変換されていますが、これはstrtoupperが非文字列を処理しようとした結果です。

ユーザーデータの渡し方

array_walk_recursive関数の第3引数 $userdataを使用すると、コールバック関数に任意の追加データを渡すことができます。

例1:ユーザーデータ(税率)を使ってすべての数値に税金を適用する

この例では、多次元配列内のすべての数値に対して、ユーザーデータとして渡された税率を適用して値を更新します。

<?php
$financialData = [
    '売上' => 1000.50,
    '費用' => [
        '給与' => 500.00,
        '家賃' => 200.00
    ],
    '税率' => 0.08 // この値は税率自体なので、計算対象から除外したい
];

$globalTaxRate = 0.10; // 10%の税率をユーザーデータとして渡す

echo "--- 税率適用前 ---" . PHP_EOL;
print_r($financialData);

array_walk_recursive($financialData, function(&$value, $key, $tax) {
    // 数値であり、かつキーが '税率' ではない要素にのみ税金を適用
    if (is_numeric($value) && $key !== '税率') {
        $value = $value * (1 + $tax);
    }
}, $globalTaxRate); // $globalTaxRate を $userdata として渡す

echo "--- 税率適用後 ---" . PHP_EOL;
print_r($financialData);
// 出力例:
// --- 税率適用前 ---
// Array
// (
//     [売上] => 1000.5
//     [費用] => Array ( [給与] => 500 [家賃] => 200 )
//     [税率] => 0.08
// )
// --- 税率適用後 ---
// Array
// (
//     [売上] => 1100.55
//     [費用] => Array ( [給与] => 550 [家賃] => 220 )
//     [税率] => 0.08 // '税率'キーの値は変更されない
// )
?>

$financialDataという、売上や費用が入った配列を用意しています。

この$financialData配列にたいして、array_walk_recursive関数を使っています。
$globalTaxRate(10%)は税率として、第3引数に渡しています。

コールバック関数では、$taxで第3引数の内容を受け取ります。
キーが税率以外の場合には、値にたいして、税率10%を乗せて計算した値を上書きしています。

結果を確認すると、キーが税率の項目以外は、税率を乗せて計算されていることが確認できます。

array_walk_recursive関数を使う際の注意点

array_walk_recursive関数を使う際の注意点です。

元の配列が変更される可能性がある

コールバック関数の第1引数を参照渡し (&) にした場合、元の配列が直接変更されます。この破壊的な性質を理解して使用してください。

キーは考慮されるが、親のキーは渡されない

コールバック関数には現在の要素のキーが渡されますが、その要素がどの親配列に属しているか(親のキー)は直接渡されません。
複雑な階層構造の中で親の情報を元に処理を分岐させたい場合は、foreach ループを再帰的に使用する方が適している場合があります。

配列要素はスキップされる

array_walk_recursive関数は、要素が配列である場合はその配列を再帰的に処理しますが、その配列自体はコールバック関数に渡されません。
コールバック関数に渡されるのは、スカラ値(数値、文字列、ブール値など)のみです。

戻り値は bool

array_walk_recursive関数自体の戻り値は、処理が成功したかどうかを示すtrueまたはfalseです。
コールバック関数が返した値は array_walk_recursive の戻り値には影響しません。

配列の構造変更

コールバック関数内で配列の要素を追加したり削除したりすると、予期せぬ結果になる可能性があります。
array_walk_recursive関数は、反復処理中に配列の構造が変更されることを想定していません。

array_walk_recursiveとarray_walkの違い

機能 array_walk_recursive array_walk
対象配列 多次元配列のすべての要素(再帰的に) 一次元配列の要素のみ
処理対象 スカラ値の要素のみがコールバックに渡される スカラ値とネストされた配列要素の両方が渡されるが、配列要素はそれ以上展開されない
キーの保持 する する
参照渡し 可能(&$value 可能(&$value
ユーザーデータ 渡せる 渡せる

使い分けの目安

  • array_walk_recursive: 多次元配列のすべてのスカラ要素(値)に対して、一律の処理(変換、クリーンアップ、ログ出力など)を適用したい場合に最適です。
  • array_walk: 一次元配列の各要素に対して、直接変更を加えたい場合や、特定の副作用を発生させたい場合に最適です。

まとめ

PHPの array_walk_recursive 関数は、多次元配列のすべてのスカラ要素(値)に対して、ユーザー定義関数を再帰的に適用するための強力なツールです。
ネストされたデータ構造内の値を一括で変換したり、特定の処理を実行したりする際に非常に便利です。

参照渡しによる要素の変更、ユーザーデータの渡し方、そして array_walkとの使い分けを理解して、array_walk_recursive関数を効果的に活用し、より効率的で読みやすいPHPコードを作成しましょう。

PHP

コメント