基礎

PHPのnull合体演算子(??)|nullチェックを簡潔に書く方法

PHPのnull合体演算子 ?? は、左辺の値が null でなければ左辺を、null であれば右辺を返す演算子です。PHP 7.0で導入され、isset() と三項演算子を組み合わせていた冗長なnullチェックを、1つの演算子でスッキリ書けるようになりました。

フォーム入力のデフォルト値設定、設定値の取得、APIレスポンスの処理など、nullになりうる値を安全に扱うあらゆる場面で活躍します。

基本的な使い方

PHP
<?php
$name = null;
echo ($name ?? "ゲスト") . "\n";

$name = "田中";
echo ($name ?? "ゲスト") . "\n";

// 未定義の変数にも使える(Warningが出ない)
echo ($undefinedVar ?? "デフォルト値") . "\n";
実行結果
ゲスト
田中
デフォルト値

$namenull の場合は右辺の「ゲスト」が返され、値がある場合はその値がそのまま返されます。重要な点として、未定義の変数に対しても警告なしで使えます。

issetとの比較

??isset() + 三項演算子の省略形です。

PHP
<?php
$data = ["name" => "田中", "age" => 30];

// 従来の書き方
$email1 = isset($data["email"]) ? $data["email"] : "未設定";

// null合体演算子(同じ結果)
$email2 = $data["email"] ?? "未設定";

echo "従来: {$email1}\n";
echo "??: {$email2}\n";

// ネストした配列でも安全
$config = ["db" => ["host" => "localhost"]];
$port = $config["db"]["port"] ?? 3306;
echo "ポート: {$port}\n";
実行結果
従来: 未設定
??: 未設定
ポート: 3306

チェーン(連続使用)

?? は連続して使えます。左から順に評価され、最初にnullでない値が返されます。

PHP
<?php
$primary = null;
$secondary = null;
$fallback = "デフォルト";

// 左から順にnullでないものを探す
echo ($primary ?? $secondary ?? $fallback) . "\n";

$secondary = "セカンダリ値";
echo ($primary ?? $secondary ?? $fallback) . "\n";

// 設定値の優先順位
$envLang = null;           // 環境変数
$configLang = null;        // 設定ファイル
$defaultLang = "ja";       // デフォルト
$lang = $envLang ?? $configLang ?? $defaultLang;
echo "言語: {$lang}\n";
実行結果
デフォルト
セカンダリ値
言語: ja

null合体代入演算子(??=)

PHP 7.4で追加された ??= は、変数がnullの場合にのみ代入する演算子です。

PHP
<?php
$settings = [
    "theme" => "dark",
];

// nullの場合のみ代入
$settings["theme"] ??= "light";    // 既に値があるので変わらない
$settings["language"] ??= "ja";    // 未定義なので代入される
$settings["fontSize"] ??= 14;      // 未定義なので代入される

print_r($settings);
実行結果
Array
(
    [theme] => dark
    [language] => ja
    [fontSize] => 14
)

実用的な例

PHP
<?php
// フォーム入力のデフォルト値($_GETの代わりに配列で模擬)
$get = ["page" => "3"];
$page = (int)($get["page"] ?? 1);
$sort = $get["sort"] ?? "created_at";
$order = $get["order"] ?? "desc";

echo "ページ: {$page}, ソート: {$sort}, 順序: {$order}\n";

// APIレスポンスの安全な値取得
$response = [
    "data" => [
        "user" => [
            "name" => "田中太郎",
            "profile" => null,
        ]
    ]
];

$name = $response["data"]["user"]["name"] ?? "不明";
$bio = $response["data"]["user"]["profile"]["bio"] ?? "自己紹介なし";
$avatar = $response["data"]["user"]["avatar"] ?? "/img/default.png";

echo "名前: {$name}\n";
echo "自己紹介: {$bio}\n";
echo "アバター: {$avatar}\n";
実行結果
ページ: 3, ソート: created_at, 順序: desc
名前: 田中太郎
自己紹介: 自己紹介なし
アバター: /img/default.png
??と?:の違いに注意

??null のみをチェックします。一方、?:(Elvis演算子)は false0""(空文字)、null など falsy な値すべてをチェックします。0"" を有効な値として扱いたい場合は ?? を使いましょう。

ポイント

PHP 8.0の ?->(nullsafe演算子)と組み合わせると、さらに安全なチェーンアクセスが可能です。例えば $user?->getAddress()?->getCity() ?? "不明" のように、途中で null が返されても安全にデフォルト値を設定できます。

まとめ

  • ?? は左辺がnullでなければ左辺を、nullなら右辺を返す
  • isset() + 三項演算子の省略形として使える
  • チェーン($a ?? $b ?? $c)で複数の候補から最初のnull以外を取得
  • ??= でnullの場合のみ代入できる(PHP 7.4+)
  • ?: との違いに注意:?? はnullのみ、?: はfalsyな値すべてが対象