🐘

PHP で連想配列の分割代入でエラーが発生するケース

2024/02/24に公開

こんにちは。 SAW です。
最近 マリオカート8 デラックス のオンラインプレイに挑戦しはじめました。
地道にレートを上げていきたいです(笑)

PHP 7.1.0 から 連想配列の分割代入 ができるようになりました。
JavaScript でオブジェクトの分割代入と同様に、連想配列の要素をそれぞれ変数に一括で代入できます。

ただし、 JavaScript のオブジェクトの分割代入と異なる点があります。
PHP の場合、 キーが連想配列にない場合 には、エラーが発生します。

本記事では、 PHP の連想配列で分割代入をする場合にエラーが発生するケースと、エラーを回避する方法について紹介します。
なお、本記事では PHP のバージョンが 8.2.x 系 で動作を確認しています。

連想配列の分割代入でエラーが発生するケース

連想配列を分割代入する際に、存在しないキーを指定するとエラーが発生します。
PHP 8.0.0 から、連想配列に E_WARNING レベルのエラーが発行されます。
(7.x 系以前は E_NOTICE レベルのエラーが発行されます。)

エラーとなる分割代入のコード例は以下の通りです。

連想配列に存在しないキーを指定した分割代入の例
$array = [
    'hoge' => 1,
    'piyo' => 2,
];

[
    'hoge' => $hoge,
    'piyo' => $piyo,
    'foo' => $foo, // $array['foo'] は存在しないためエラー
] = $array;

存在しないキーにアクセスすると、以下のようなエラーメッセージが発行されます。

エラーメッセージ
Undefined array key "foo"

エラーの回避方法

連想配列の分割代入でのエラーを回避する方法として、次の方法が考えられます。

  • 連想配列にキーが存在する場合はその値を変数に代入する
  • 連想配列にキーが存在しない場合はデフォルト値を変数に代入する

実現手順は以下の通りです。

  1. 連想配列のキーとデフォルト値の対応づけをした連想配列を作成する
  2. 分割代入する対象の連想配列と 1 で作成した連想配列をマージする
  3. 2 でマージした連想配列に対して分割代入する

文章ではわかりづらいので、実際にコード例を以下に示します。

連想配列にキーが存在しない場合はデフォルト値を変数に代入するコード例
// 対象のキーとデフォルト値を対応付けした連想配列を作成
$default = [
    'hoge' => null,
    'piyo' => null,
    'foo' => null,
];

// 分割代入する対象の連想配列
$array = [
    'hoge' => 1,
    'piyo' => 2,
];

[
    'hoge' => $hoge, // $hoge = 1
    'piyo' => $piyo, // $piyo = 2
    'foo' => $foo, // $foo = null
] = [...$default, ...$array];

コード例の補足解説

連想配列の分割代入をする際に、 $default$array をスプレッド演算子 (...) を利用してマージしています。
ただし、連想配列をマージする際には 順序 に気をつける必要があります。

同じキーを持つ連想配列をマージする場合、 最後の連想配列のキーの値 が適用されます。
上記のコード例の場合、 $default のキーの値を $array で上書きするために、 $default の後ろに $array を指定します。

連想配列のマージする順序を変えた場合の結果はそれぞれ以下のようになります。

マージする連想配列の順序を変えた場合の結果
[...$default, ...$array]
// ['hoge' => 1, 'piyo' => 2, 'foo' => null]

[...$array, ...$default]
// ['hoge' => null, 'piyo' => null, 'foo' => null]

まとめ

本記事のまとめは次の通りです。

  • PHP の連想配列を分割代入する際にエラーとなるケースを紹介
    • 存在しないキーが指定されているとエラー
  • エラーの回避方法を紹介
    • デフォルト値を設定した連想配列と代入対象の連想配列をマージして分割代入することでエラーを回避

PHP と JavaScript の分割代入では、挙動に異なる部分があることを知れて勉強になりました。

参考文献

https://www.php.net/manual/en/language.types.array.php

Discussion