読者です 読者をやめる 読者になる 読者になる

It's raining cats and dogs.

無駄なことなんてないはず

多次元配列をうまいことマージしてくれるarray_replace_recursive便利

今更感あるけど、array_replace_recursive というメソッドが便利だった。

設定ファイルなんかはphpでサクッと書いちゃうことが多い。例えば

<?php
return [
    'key1' => [
        'key11' => 'val11',
        'key12' => 'val12'
    ],
    'key2' => 'val2'
];

みたいなファイルにしておけば

<?php
$config = require '/path/to/config.php';

な感じでrequireするだけだし、phpのコードでしかないから早いし、パースしなくていいし、記述ミスがあってもsyntax errorでコケてくれるし、OPcacheでもかませればメモリに乗ってくれるしいいコトづくめ。
なんだけど、例えばベースのconfig用配列をrequireした後に、個別の処理でconfigを上書きしたい時があったりしたときに、array_mergeでマージしてしまうと子要素がまるっと上書きされてしまうので、泥臭く手でマージしたりしてたんだけど、表題のarray_replace_recursive を使えば簡単に解決することがわかった。

たとえば、array_mergeだと

<?php
$a = [
    'key1' => [
        'key11' => 'val11',
        'key12' => 'val12'
    ],
    'key2' => 'val2'
];
// key12だけ上書きしたい
$b = [
    'key1' => [
        'key12' => 'hoge12'
    ]
];

var_dump(array_merge($a, $b));

// key11がなくなっちゃった!
array(2) {
  'key1' =>
  array(1) {
    'key12' =>
    string(6) "hoge12"
  }
  'key2' =>
  string(4) "val2"
}

こんな感じで子要素がまるっと上書きされてしまう。
でも、array_replace_recursive だと

<?php
$a = [
    'key1' => [
        'key11' => 'val11',
        'key12' => 'val12'
    ],
    'key2' => 'val2'
];
// key12だけ上書きしたい
$b = [
    'key1' => [
        'key12' => 'hoge12'
    ]
];

var_dump(array_replace_recursive($a, $b));

// key12だけ上書きされた!
array(2) {
  'key1' =>
  array(2) {
    'key11' =>
    string(5) "val11"
    'key12' =>
    string(6) "hoge12"
  }
  'key2' =>
  string(4) "val2"
}

こんな具合に key11 を残したまま key12 だけ上書きしてくれた。便利!