【PHP】配列結合するときのarray_merge()と+演算子の挙動の違い

久しぶりにPHPを書いたのですが配列の扱いでちょっと驚いたので書いておきます。それは、一次元配列を結合しようとしたときのことです。

<php?
$errorMsg1 = array('名前は必須入力です', 'メールアドレスは必須入力です', '年齢は必須入力です');
$errorMsg2 = array('住所を選択してください', '電話番号に不備があります', '生年月日に不備があります');
$result = $errorMsg1 + $errorMsg2;
var_dump($result);
?>

// 出力結果
array(3) {
  [0]=>
  string(27) "名前は必須入力です"
  [1]=>
  string(42) "メールアドレスは必須入力です"
  [2]=>
  string(27) "年齢は必須入力です"
}

ん?最初のエラーメッセージしか表示されずerrorMsg2が消えている…array_mergeしてみたらどうなるんだろう?

<?php
$errorMsg1 = array('名前は必須入力です', 'メールアドレスは必須入力です', '年齢は必須入力です');
$errorMsg2 = array('住所を選択してください', '電話番号に不備があります', '生年月日に不備があります');
$result = array_merge($errorMsg1, $errorMsg2);
var_dump($result);
?>

// 出力結果
array(6) {
  [0]=>
  string(27) "名前は必須入力です"
  [1]=>
  string(42) "メールアドレスは必須入力です"
  [2]=>
  string(27) "年齢は必須入力です"
  [3]=>
  string(33) "住所を選択してください"
  [4]=>
  string(36) "電話番号に不備があります"
  [5]=>
  string(36) "生年月日に不備があります"
}

期待通りに結合ができました。

原因

PHPで+演算子を使って結合をした場合、両方の配列に同じキーが存在する場合は、前方の配列が優先されるという性質があるようです。

そのため、最初の例では$errorMsg1の結果のみが出力されたんですね。

一方、array_merge()の場合は、数字インデックスの場合に限り、数字を振り直すという特徴があるため、結合元と結合先のインデックスが重複していても特に問題なく結合ができるんですね。

そのため、下記のようなキーが設定されている連想配列であれば、+演算子でも問題なく動作します。

<?php
$errorMsg1 = array('name' => '名前は必須入力です', 'mailAddress' => 'メールアドレスは必須入力です', 'age' => '年齢は必須入力です');
$errorMsg2 = array('address' => '住所を選択してください', 'tel' => '電話番号に不備があります', 'birthday' => '生年月日に不備があります');
$result = $errorMsg1 + $errorMsg2;
var_dump($result);
?>

// 出力結果
array(6) {
  ["name"]=>
  string(27) "名前は必須入力です"
  ["mailAddress"]=>
  string(42) "メールアドレスは必須入力です"
  ["age"]=>
  string(27) "年齢は必須入力です"
  ["address"]=>
  string(33) "住所を選択してください"
  ["tel"]=>
  string(36) "電話番号に不備があります"
  ["birthday"]=>
  string(36) "生年月日に不備があります"
}

結論

PHPで配列を結合する場合は、結合する配列の形(添字が数字なのか、連想配列なのか)によって注意が必要ということです。

キーが一意の連想配列の場合は、+演算子を利用すれば問題なさそうです。ただし、重複した際は結合元の配列の値が優先されるので注意が必要です。

添字が数字の場合で添字番号に意味を持たせていない場合は、array_mergeを使うことで添字を振り直した新たな配列を生成することができます。

ただ、数字の添字に意味を持たせている場合は、+演算子を使うことで、添字を固定化することができます。

つまり、期待する値によってこれらを使い分ける必要があります。配列結合時はこの2つの挙動の違いを知っておくと良さそうです。

参考文献