https://www.php.net/manual/ja/migration70.new-features.php#migration70.new-features.null-coalesce-op
null 合体演算子 (??) がシンタックスシュガーとして追加されました。 三項演算子と isset() を組み合わせる よくありがちなパターンを、より簡単に書くためのものです。 この演算子は、もし第一オペランドが非 null の値であればそれを返し、 そうでない場合は第二オペランドを返します。
php
1$username = $_GET['user'] ?? 'nobody';2// 上のコードは、次のコードと同じ意味です。3$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
と書かれていますが、実際には同値ではありません。
上記の書き換えが同値でない結果となるコード
https://onlinephp.io/c/ce950
code
php
1<?php2class Foo1 {3 public function __get($prop) { return 'prop by __get()'; }4}5class Foo2 {6 public function __isset($prop) { return true; }7}8class Foo3 {9 public function __get($prop) { return 'prop by __get()'; }10 public function __isset($prop) { return true; }11}12 13for ($i = 1; $i <= 3; ++$i) {14 $class = "Foo{$i}";15 echo "===== result of {$class} =====", PHP_EOL;16 $foo = new $class;17 $result1 = $foo->bar ?? 'default';18 $result2 = isset($foo->bar) ? $foo->bar : 'default';19 $result3 = !@is_null($foo->bar) ? $foo->bar : 'default';20 var_dump($result1, $result2, $result3);21}
output
php
1===== result of Foo1 =====2string(15) "prop by __get()"3string(7) "default"4string(15) "prop by __get()"5===== result of Foo2 =====6 7Warning: Undefined property: Foo2::$bar in /home/user/scripts/code.php on line 188string(7) "default"9NULL10string(7) "default"11===== result of Foo3 =====12string(15) "prop by __get()"13string(15) "prop by __get()"14string(15) "prop by __get()"
Foo1 では __get() のみを定義し、Foo2 では __isset() のみを定義しています。Foo3 ではその両方を定義しています。
Foo3 では、書き換えの結果が一致するようですが、Foo1 と Foo2 はそうではありません。
isset() ではなく、むしろ @is_null() での書き換えの結果に一致しているようです。
Foo1 の結果が異なることについては、PHPマニュアルでも note として指摘されていますが、マニュアルには反映されていません。
- (q1) PHPマニュアルでは「isset() との書き換えが同値」であるように書かれていますが、実際には上記の通り異なる挙動となっている「経緯」について言及されている文献をご存知でしたらご教示ください。
- (q2) この挙動の違いについて言及している文献をご存知でしたらご教示ください。
- (q3) 他にこれに関する関連情報や補足情報があればご教示ください。
PHPマニュアルに「null合体演算子」の正確な仕様を記述しておいてもらいたいと思っているのですが、そのような依頼やトピックを立てるプラットフォームはあるのでしょうか。もしご存知でしたらこちらも併せて教えていただけると助かります。

0 コメント