??は、左側の値が存在してnullでなければその値を、そうでなければ右側の値を返します:$name = $_GET['name'] ?? 'Guest';。キーを直接読む場合と違い、変数や配列キーが存在しなくても警告を出しません。
最初の実行ではクエリ文字列がないので、どちらも既定値が使われます。PageタブのリンクをクリックするとURLの値が$_GETに入った状態でスクリプトがもう一度実行されます。その最初の実行で??なしに$_GET["name"]を読むと、通常のPHPの設定ではWarning: Undefined array key "name"が表示されます。リクエストのデータについては_POSTのページで詳しく説明しています。
??はisset()チェックの短縮形
$a ?? $bはisset($a) ? $a : $bとまったく同じ意味です。変数、任意の深さの配列キー、オブジェクトのプロパティに使え、欠けている最初の部分で文句を言わずに止まります。
この確認はissetと同じものなので、存在していても値がnullのキーは既定値になります。
??を連鎖させて複数の候補を試す
??は右結合で、いくつでも連鎖させられます。PHPは、設定されていてnullでない最初のオペランドを返します。
??=はnullのときだけ代入する
$a ??= $bは、$aが未設定かnullのときだけ$bを$aに格納します。既定値を埋めたり、何かを一度だけ計算して使い回したりするいちばん短い方法です。
??=の右辺は代入が行われるときだけ評価されるので、computing 4は1回しか表示されません。
??と?:(省略形の三項演算子)の違い
??はnullかどうかを、?:はtrueと評価されるかどうかを調べます。0、""、"0"のような値では答えが変わります。
"0"という数量は正当な入力です。??はそれを残し、?:は置き換えます。?:だけでは存在しないキーについて警告が出るので、このブロックでは($inputs[$key] ?? null) ?: ...のように包んでいます。?:自体については三項演算子のページで扱っています。
nullsafe演算子?->
?->は同じ考え方のオブジェクト版で、PHP 8で追加されました。左側のオブジェクトがnullなら連鎖全体がそこで止まり、Call to a member function getAddress() on nullのようなErrorを投げる代わりにnullを返します。既定値には最後に??を付けます。
ユーザー2は存在しますが住所がなく、ユーザー3はそもそも存在しません。どちらもエラーなしで?? "unknown"の既定値にたどり着きます。
よくあるミス:??は優先順位が低い
??は.や算術演算子より結びつきが弱いです。そのため"Count: " . $count ?? 0では、PHPはまず"Count: " . $countという文字列を作り、それは決してnullにならないので、既定値は使われません。
??の式がより大きな式の中にあるときは、必ず括弧で囲みましょう。
よくある質問
PHPの??はどういう意味ですか?
??はnull合体演算子です。$a ?? $bは、$aが存在してnullでなければ$aを、そうでなければ$bを返します。isset($a) ? $a : $bの短縮形で、$aや配列キーが未定義でも警告を出しません。
PHPの??と?:の違いは何ですか?
??は左辺がnullか未設定のときだけ代わりの値を使うので、0 ?? 5は0、'' ?? 'x'は''です。?:は左辺がfalseと評価されれば代わりの値を使うので、0 ?: 5は5です。また?:は未定義の変数やキーについて警告を出しますが、??は出しません。
PHPの??=は何をしますか?
$a ??= $bは、$aがnullか未設定のときだけ$bを$aに代入し、そうでなければ$aをそのままにします。$a = $a ?? $b;の短縮形で、PHP 7.4で追加されました。
PHPのnullsafe演算子?->とは何ですか?
$obj?->method()は、$objがnullでないときだけメソッドを呼び出します。nullなら、エラーを投げる代わりに連鎖全体がnullを返します。既定値には??と組み合わせます:$user?->getAddress()?->city ?? 'unknown'。PHP 8.0で追加されました。