Code Fix

中級

?? を使わずに存在しないキーへアクセスするとWarningが混ざる

配列のキーが存在するか分からない場合、??演算子を使えばWarningを出さずにデフォルト値を指定できます。??を使わずにそのままアクセスすると、Undefined array keyのWarningが出力に混ざります。

なぜエラーが出ないのか

出力:
(エラーなし)
PHPは何も報告しません。文法として正しいためです
出力:
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  <?php
 2  $config = ["timeout" => 30];
 3  $retries = $config["retries"] or  3;
                                   ^
 4  echo $retries;
出力: Warning: Undefined array key "retries" in main.php on line 3期待: 3 (Warningなしで済むはずが混ざってしまいます)

orは真偽値としての判定であってデフォルト値の指定にはなりません。存在しないキーへの直接アクセスがそのまま実行され、Warningが出力に混ざります。??を使えば1行でWarning無しにデフォルト値を指定できます。

直し方: or を ?? にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  <?php
 2  $settings = ["theme" => "dark"];
 3  $lang = $settings["lang"] or  "ja";
                               ^
 4  echo $lang;
出力: Warning: Undefined array key "lang" in main.php on line 3期待: ja (Warningなしで済むはずが混ざってしまいます)

orでは存在しないキーへのアクセス自体は防げず、Warningが出力に混ざります。??を使う必要があります。

直し方: or を ?? にします。

この問題を解いてみる →

パターン3

 1  <?php
 2  $env = ["debug" => false];
 3  $level = $env["level"] or  "info";
                            ^
 4  echo $level;
出力: Warning: Undefined array key "level" in main.php on line 3期待: info (Warningなしで済むはずが混ざってしまいます)

orは値の存在確認をしないため、存在しないキーへのアクセスがそのまま実行されWarningになります。

直し方: or を ?? にします。

この問題を解いてみる →

パターン4

 1  <?php
 2  $opts = ["color" => "red"];
 3  $size = $opts["size"] or  "M";
                           ^
 4  echo $size;
出力: Warning: Undefined array key "size" in main.php on line 3期待: M (Warningなしで済むはずが混ざってしまいます)

orは真偽値としての判定であってデフォルト値の指定にはなりません。??を使う必要があります。

直し方: or を ?? にします。

この問題を解いてみる →

パターン5

 1  <?php
 2  $prefs = ["sound" => true];
 3  $vol = $prefs["volume"] or  50;
                             ^
 4  echo $vol;
出力: Warning: Undefined array key "volume" in main.php on line 3期待: 50 (Warningなしで済むはずが混ざってしまいます)

orでは存在しないキーへのアクセス自体は防げず、Warningが出力に混ざります。

直し方: or を ?? にします。

この問題を解いてみる →

よくある誤解

「isset()でチェックしてから使うのが唯一の方法」というのは古いスタイルです。??演算子を使えば1行でデフォルト値の指定とWarning回避を同時に行えます。

実務での勘所

PHP 7.4以降は、??をさらに発展させたヌル合体代入演算子??=も使えます。$config['timeout'] ??= 30;のように書くと、$config['timeout']が未設定またはnullのときだけ30を代入し、すでに値が入っていれば何もしません。「無ければ既定値を設定し、あれば触らない」という初期化パターンを、if文や??を使った書き方より短く1行で表現できます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)