連想配列の初期化をしている他人のコード(Null 合体演算子を使って初期化していた)を読んでいて、あまり自分では書くケースが無さそうなパターンだったので、どんな書き方がベターなのかなと悩みました。
結論としては、Null 合体演算子は優秀だし簡潔で分かりやすくて良さそうだと思いました。
気になったコードのサンプル
該当のコードは簡略化すれば以下のような感じです。
連想配列をデフォルト値で上書きするカタチで初期化していました。
function foo(array $params) {
$params['foo'] = $params['foo'] ?? 'A';
// ...
}
連想配列のオプションで多機能なメソッドの処理内容を切り替えるパターンで、そもそも設計が不味いと思うし、無理やり納得できる例に置き換えるなら、POST された可変長の連想配列を素の PHP で処理するようなときとかでしょうか。
Null 合体演算子と等価な別の記述
Null 合体演算子は、isset($var) ?: ...
もしくは if (isset($var)) ...
と同等なはずなので、人によっては if 文を使ったりしそうです。
if 版
個人の主観の話しになってくるのかもですが、自分は冗長かなと思います
if (!isset($params['foo'])) {
$params['foo'] = 'default';
}
上書きだから条件がちょっと変だけど、変数への代入であれば if else な感じに。
if (!isset($params['foo'])) {
$foo = $params['foo'];
} else {
$foo = 'default';
}
三項演算子版
これも上書きだから変に繰り返し感が増してますが、それを差し引いても Null 合体演算子よりは冗長に思います。
$params['foo'] = isset($params['foo']) ? $params['foo'] : 'default';
isset() を省略しちゃうバグ
ありそうなバグとしては isset()
を使わないというやつで、Notice: Undefined index
かつ ""
0
false
などの値も上書きしてしまうってのがありそうです。
if (!$params['foo']) {
$params['foo'] = 'default';
}
もしくは、こっちの方がありそうかも。
$params['foo'] = $params['foo'] ? $params['foo'] : 'default';
unless ?
実は、自分が最初に考えたのが上記のバグ版と似たようなパターンでした……。
unless ぽい感じで書けそうじゃない?と思ったけど、上記と同じ理由で全然ダメでした。
$params['foo'] ?: $params['foo'] = 'default';
// @$params['foo'] ?: $params['foo'] = 'default';
// とすれば、Notice: Undefined index だけは回避できるけど
ちゃんと書けば unless ぽく使えそうな気がしないでもないですが、個人的には何をしているのか一見分かり難いから、Null 合体演算子のほうが良いかなと思いました。
isset($params['foo']) ?: $params['foo'] = 'A';
まとめ
そう考えると Null 合体演算子は簡潔に isset
をできる方法として優秀だし、コードが分かりやすいから使い勝手がいいなと思いました。
対抗馬としては、null
と Undefined index
の区別が必要だった場合に、array_key_exists()
とかですかね。
$params['foo'] = array_key_exists($params['foo']) ? $params['foo'] : 'default';