PHPのisset関数の使い方|配列チェックとempty/??との違い

基本文法・構文ガイド
  • カテゴリ: 変数・配列の存在チェック(PHP標準構文)
  • 対象バージョン: PHP 7.4 〜 8.4(言語構文として長期的に安定。null合体演算子??はPHP 7.0以降)
  • 主な関数/構文: isset() / empty() / is_null() / array_key_exists() / ??(null合体演算子)
  • 関連: empty関数 / 連想配列の基礎 / Laravelでのisset・null判定
  • 変更履歴: 言語構文自体の仕様は長期的に安定。PHP 7.0でnull合体演算子??、PHP 7.4で型付きプロパティが追加され、isset()との組み合わせ方の選択肢が増えた

要点(TL;DR)

  • isset($var)は「変数が定義済みで、かつnullではない」ときにtrueを返す言語構文。未定義変数に使ってもエラーにならず安全に判定できる
  • 配列のキー確認はisset($arr['key'])、ネストした配列・オブジェクトのプロパティもisset($arr['a']['b'])のようにチェーンして一度に確認できる
  • 複数の変数をまとめてチェックするならisset($a, $b, $c)。すべてが定義済みかつnullでない場合のみtrue
  • 値がnullかどうかしか見ないので、0""falseは「セットされている」扱いになる。「空かどうか」を見たい場合はempty()を使う
  • デフォルト値を当てたいだけなら、isset()のif文より??(null合体演算子)や??=のほうが1行で書けて読みやすい

概要

issetはPHPの言語構文(関数ではなく特殊な構文)で、指定した変数・配列要素・オブジェクトのプロパティが「定義されていて、かつnullではない」かどうかを確認します。$_POST$_GETのような未定義かもしれない配列キーへ直接アクセスするとPHPは警告(Undefined array key)を出しますが、isset()で先にチェックしてからアクセスすればこの警告を避けられます。この記事では基本構文から配列・オブジェクトでの使い方、empty()??との使い分け、よくある間違いまでを実際に動かせるコード例とともに解説します。

構文 / シグネチャ

bool isset(mixed $var, mixed ...$vars)

第一引数だけでなく可変長引数を受け取れるため、isset($a, $b, $c)のように複数の変数を一度に渡せます。この場合、渡したすべての変数が定義済みかつnullでないときだけtrueを返します(1つでも条件を満たさなければ、その時点で残りの評価を打ち切る短絡評価)。関数ではなく言語構文なので、変数・配列要素・プロパティ以外の「式」(関数の戻り値など)を直接渡すことはできません。

isset・empty・is_null・array_key_existsの違い

関数/構文trueになる条件未定義変数に使った場合主な用途
isset($var)定義済み かつ nullではないエラーにならずfalse変数・配列キーが「使える状態」かの確認
empty($var)未定義、またはnull/0/""/"0"/false/空配列エラーにならずtrue「実質的に空」かどうかの確認
is_null($var)値がnullと厳密に一致PHP Warning: Undefined variableが発生変数が定義済みである前提でnullかを確認
array_key_exists('key', $arr)配列にキーが存在する(値がnullでもtrue)-(配列自体は必要)値がnullでもキーの有無だけを見たいとき

最も混同しやすいのがisset()array_key_exists()の違いです。配列のキーにnullを代入した場合、isset($arr['key'])falseを返しますが、array_key_exists('key', $arr)trueを返します。「キー自体があるかどうか」を厳密に確認したい場合はarray_key_exists()を使ってください。

<?php

$data = ['name' => null];

var_dump(isset($data['name']));            // bool(false)
var_dump(array_key_exists('name', $data)); // bool(true)

使用例

基本的な使い方

<?php

$name = "John Doe";

if (isset($name)) {
    echo "変数nameはセットされています。";
} else {
    echo "変数nameはセットされていません。";
}
// 出力: 変数nameはセットされています。

$age = null;
var_dump(isset($age)); // bool(false) nullなのでfalse

var_dump(isset($undefinedVar)); // bool(false) 未定義変数でもエラーにならない

未定義の変数をisset()に渡してもエラーや警告は発生しません。これはisset()が「変数へのアクセスを試みる前に」定義状況を確認する特殊な構文だからです。

複数変数をまとめてチェックする

<?php

$firstName = "John";
$lastName = "Doe";
$middleName = null;

var_dump(isset($firstName, $lastName));              // bool(true)
var_dump(isset($firstName, $lastName, $middleName)); // bool(false) middleNameがnullのため

配列のキー・ネストした要素をチェックする

<?php

$user = [
    'name' => 'Taro',
    'profile' => [
        'email' => 'taro@example.com',
    ],
];

var_dump(isset($user['name']));                  // bool(true)
var_dump(isset($user['profile']['email']));      // bool(true) ネストしたキーもチェーンで確認できる
var_dump(isset($user['profile']['phone']));      // bool(false) 存在しないキー
var_dump(isset($user['address']['zip']));        // bool(false) 途中のキーが無くてもエラーにならない

isset()はチェーンの途中のキーが存在しなくても警告を出さずにfalseを返します。深いネストの存在確認を安全に行える点がisset()の大きな利点です。オブジェクトのプロパティも同様にisset($obj->prop->child)のように確認できます。

Webフォームの入力チェック($_POST)

<?php

if (isset($_POST['username'], $_POST['email'])) {
    $username = $_POST['username'];
    $email = $_POST['email'];
    // バリデーション・保存処理などを続ける
} else {
    echo "必須項目が入力されていません。";
}

$_POST$_GETのキーは送信されなければ存在しません。直接アクセスするとUndefined array keyの警告が出るため、isset()で先に存在確認してからアクセスするのが定石です。

デフォルト値を当てるならnull合体演算子(??)

<?php

// isset()を使ったif文での書き方
if (isset($_GET['page'])) {
    $page = $_GET['page'];
} else {
    $page = 1;
}

// null合体演算子(??)を使うと1行で書ける
$page = $_GET['page'] ?? 1;

// 変数自体に代入したいときは null合体代入演算子(??=)
$config['timeout'] ??= 30;

$a ?? $bは「$aisset($a)でtrueならその値、falseなら$b」を返す構文で、内部的にはisset()と同じ判定基準(未定義またはnullならフォールバック)を使っています。単純に「値が無ければデフォルト値を使う」だけの用途であれば、isset()のif文より??のほうが簡潔です。

APIレスポンス(連想配列)の検証

<?php

$response = json_decode($apiResponseJson, true);

if (isset($response['data']['id'], $response['data']['name'])) {
    $id = $response['data']['id'];
    $name = $response['data']['name'];
} else {
    throw new RuntimeException('Invalid API response: required fields are missing.');
}

外部APIのレスポンス構造は必ずしも保証されないため、想定しているキーが揃っているかをisset()でまとめて確認してから後続処理に進むと、未定義キーへのアクセスによる警告やnullエラーを防げます。

よくある落とし穴・注意

  • 値が0や空文字でもisset()trueisset()が見ているのは「nullかどうか」だけです。フォーム入力で「値が空欄かどうか」を判定したい場合はisset()ではなくempty()trim($val) === ''を使う必要があります。
  • 関数の戻り値には直接使えないisset()は言語構文のため、isset(getUser())のように関数呼び出しの結果を直接渡すことはできません(構文エラー)。関数の戻り値をチェックしたい場合は、一度変数に代入してからisset($result)とするか、$result !== nullを使います。
  • キーにnullを代入すると「存在しない」扱いになる$arr['key'] = null;のように明示的にnullを代入すると、array_key_exists()trueを返す一方でisset()falseになります。「キーの有無」を知りたいのか「使える値があるか」を知りたいのかを区別しましょう。
  • 型付きプロパティ(PHP 7.4以降)が未初期化だと直接アクセスはエラーになる:クラスの型付きプロパティにデフォルト値を与えず未初期化のままアクセスするとError: must not be accessed before initializationが発生します。isset($obj->prop)で先に確認すればエラーにならず、安全に判定できます。
  • マジックメソッド__isset()が定義されたクラスでは挙動が変わる:オブジェクトに__isset()マジックメソッドが実装されている場合、プロパティが実際に存在しなくてもisset($obj->prop)の結果はそのメソッドのロジックに従います。フレームワークが提供するオブジェクト(Eloquentモデルなど)で意図しない結果になったときは、このマジックメソッドの実装を確認してください。

代替・関連APIとの比較

方法向いている場面特徴
isset($var)変数・配列キー・プロパティが「使える状態」かの確認未定義でもエラーにならない。値がnullならfalse
$var ?? $default値が無ければデフォルト値を使いたいだけのときisset()と同じ判定基準を1行で書ける。PHP 7.0以降
$var ??= $default未設定のときだけ変数に値を代入したいとき設定済みなら何もしない。PHP 7.4以降
empty($var)「空」かどうか(0や空文字も含めて)を判定したいとき未定義変数でもエラーにならない。empty関数の詳細を参照
array_key_exists('key', $arr)値がnullでも「キーの存在」自体を確認したいとき配列専用。連想配列に厳密なキー確認をしたい場合に使う
property_exists($obj, 'prop')未初期化・privateなプロパティの存在確認値を読まずに宣言の有無だけを確認できる

トラブルシュート(症状別)

症状原因対処
フォームで「0」や空文字を入力すると未入力扱いになるisset()ではなくempty()で判定していて、0""が空とみなされている「値が本当にセットされているか」を見たいならisset()、「実質的に空でないか」を見たいならempty()を使い分ける
isset($arr['key'])がfalseなのにキーは存在すると言われるそのキーにnullが代入されているarray_key_exists('key', $arr)でキー自体の有無を確認する
isset(functionName())で構文エラーになるisset()は言語構文であり、関数の戻り値を直接渡せない一度変数に代入してからisset($result)とするか、$result !== nullで判定する
オブジェクトのプロパティで「must not be accessed before initialization」エラーが出るPHP 7.4以降の型付きプロパティが未初期化のまま直接アクセスされた直接アクセスする前にisset($obj->prop)で存在確認する
Eloquentモデルの属性でisset()の結果が想定と違うモデルの__isset()マジックメソッドの実装(アクセサやリレーションの遅延読み込みなど)が影響している属性名のtypoを確認するほか、必要ならarray_key_exists()$model->attributesToArray()で実データを確認する

よくある質問(FAQ)

Q. isset()とempty()はどちらを使えばいいですか?

A. 「変数が定義済みでnullでないか」を確認したいだけならisset()、「値が実質的に空(0""null・空配列など)でないか」まで含めて確認したいならempty()を使います。フォームの必須入力チェックのように「空文字も未入力扱いにしたい」場面ではempty()が適しています。

Q. isset()と??(null合体演算子)はどう使い分けますか?

A. 判定基準は同じです。「セットされていなければ処理を分岐する」ような複雑なロジックが必要ならif文でisset()を使い、「セットされていなければデフォルト値を使うだけ」ならより簡潔な??を使うのがおすすめです。

Q. isset($_GET[‘id’]) が常にfalseになるのはなぜですか?

A. リクエストにidパラメータが実際に含まれていない可能性が高いです。var_dump($_GET);で実際に送信されているキー名を確認してください。フォームのname属性のtypoや、GETとPOSTの取り違えもよくある原因です。

Q. Laravel(Bladeやコントローラ)でもこの記事のisset()をそのまま使えますか?

A. 素のPHPの構文なのでLaravel内でもそのまま使えます。ただし、Bladeテンプレートでは@issetディレクティブが用意されているため見た目がすっきりします。ルートパラメータやEloquentモデルでの活用例はLaravelでissetを効果的に活用する方法と実践例まとめで解説しています。

関連記事

参考リンク

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする

コメント