COMPANY SERVICE STAFF BLOG NEWS CONTACT

STAFF BLOG

スタッフブログ

TECHNICAL

テクログ

2024.12.25

【PHP】issetとemptyの戻り値をわかりやすく整理する

テクログphp

はじめに

結論から述べると、

▼ isset()

falseになるパターンだけ覚える!

・null
・未定義

▼ empty

trueになるパターンだけ覚えて、引数の型ごとにパターンを整理する!

・int:0
・float:0.0, -0.0
・string:’0′, 空文字
・bool:false
・array:空配列
・null
・未定義

※基本はこれらのパターンだけですが、例外がいくつかあるので後述します。

検証環境

・PHP:v8.4.2

issetの戻り値

issetは「変数が宣言されていること、そして null とは異なることを検査する」関数です。

参考:https://www.php.net/manual/ja/function.isset.php

issetの戻り値は、引数が次の値を取るときに「false」になります。(それ以外は「true」です。)

・null
・未定義

<?php

// null
$null = null;
var_dump(isset($null)); // false

// 未定義
var_dump(isset($undefined)); // false

そのため、falseになる2つのパターンだけを覚えて、それ以外はtrue だと押さえておくと混乱しにくくなると思います。

issetの例外

マジックメソッド「__isset」が実装されたクラスのプロパティを引数に取った場合だけ例外です。

__issetは「isset or emptyを、アクセス不能 or 存在しないプロパティに対して実行したときに起動」するマジックメソッドです。
※アクセス不能:protected or private

参考:https://www.php.net/manual/ja/language.oop5.overloading.php#object.isset

そのため、存在しないプロパティをissetの引数に取ったとしても、__issetの戻り値がtrueの場合、issetの戻り値は__issetの戻り値と同じ「true」になります。

ただし、emptyの戻り値は__issetの戻り値に影響しない点に注意が必要です。emptyの戻り値は__issetの有無や戻り値に関わらず、引数に取ったプロパティが存在しない場合は「true」、存在する場合は「false」になります。

<?php

class All_True
{
    public function __isset(string $name): bool
    {
        return true;
    }
}

$all_true = new All_True();
var_dump(isset($all_true->hoge)); // true:__issetの戻り値がtrueだから
var_dump(empty($all_true->hoge)); // true:hogeプロパティは存在しないから

class All_False
{
    public function __isset(string $name): bool
    {
        return false;
    }
}

$all_false = new All_False();
var_dump(isset($all_false->hoge)); // false:__issetの戻り値がfalseだから
var_dump(empty($all_false->hoge)); // true:hogeプロパティは存在しないから

余談:__issetの用途

__issetは、マジックメソッド「__get」と、「isset」を併用する場合に必要になります。

__issetを実装せずに、__get経由で値を取得しようとしているプロパティをissetの引数に取ったとき、存在しないプロパティへのアクセス判定が先に処理されるため、issetの戻り値は常に「false」になってしまいます。

▼ __issetを実装しない場合

<?php

class Hoge
{
    private $data;

    public function __construct()
    {
        $this->data = [];
    }

    public function __get(string $name)
    {
        return $this->data[$name] ?? null;
    }

    public function __set(string $name, $value): void
    {
        $this->data[$name] = $value;
    }
}

$hoge = new Hoge();
$hoge->fuga = 'fuga';

var_dump(isset($hoge->fuga)); // false:存在しないプロパティへのアクセス判定が先のため(ゲッターの処理が後)

▼ __issetを実装した場合

<?php

class Hoge
{
    private $data;

    public function __construct()
    {
        $this->data = [];
    }

    public function __get(string $name)
    {
        return $this->data[$name] ?? null;
    }

    public function __set(string $name, $value): void
    {
        $this->data[$name] = $value;
    }

    public function __isset(string $name): bool
    {
        return isset($this->data[$name]);
    }
}

$hoge = new Hoge();
$hoge->fuga = 'fuga';

var_dump(isset($hoge->fuga)); // true:__issetメソッドの戻り値が使用されるため

emptyの戻り値

emptyは「変数が空であるかどうかを検査する」関数です。

参考:https://www.php.net/manual/ja/function.empty.php

emptyの戻り値は、引数が次の値を取るときに「true」になります。(それ以外は「false」です。)

・int:0
・float:0.0, -0.0
・string:’0′, 空文字
・bool:false
・array:空配列
・null
・未定義

<?php

// int
var_dump(empty(0)); // true

// float
var_dump(empty(0.0)); // true
var_dump(empty(-0.0)); // true

// string
var_dump(empty('0')); // true
var_dump(empty('')); // true

// bool
var_dump(empty(false)); // true

// array
var_dump(empty([])); // true

// null
var_dump(empty(null)); // true

// 未定義
var_dump(empty($val)); // true

説明文にある「変数が空である」というのが抽象的でわかりづらいですが、emptyは次のコードと同じ役割を果たします。

!isset($var) || $var == false

そのため、emptyの戻り値は次のようにまとめることができます。

・issetの戻り値がfalseなら、emptyの戻り値は「true」
・引数がfalseとの緩やかな比較でtrueになる場合、emptyの戻り値も「true」

bool型との緩やかな比較の結果は下記リンク先から確認できます。

https://www.php.net/manual/ja/language.types.boolean.php#language.types.boolean.casting

緩やかな比較は型ごとに挙動が異なります。そのため、emptyの戻り値は 型ごとに整理して覚えておく のと、trueになる9つのパターンだけを覚えて、それ以外はfalse だと押さえておくと混乱しにくくなると思います。

emptyの例外

bool型へキャストするように動作がオーバーライドされたオブジェクトを引数に取った場合が例外です。例えば、「属性がない空要素から作成されたSimpleXMLオブジェクト」がそれに該当します。

<?php

$xml_obj = new SimpleXMLElement('<a></a>'); // 空要素から作成されたSimpleXMLオブジェクト
var_dump(empty($xml_obj)); // true

$std_obj = new stdClass(); // プロパティが存在しないオブジェクト
var_dump(empty($std_obj)); // false

参考:https://www.php.net/manual/ja/language.types.boolean.php#language.types.boolean.casting

おわりに

issetとemptyの戻り値で混乱している人の一助になれば幸いです。

この記事を書いた人

ノコ

入社年2021年

出身地岩手

業務内容Web開発

特技・趣味ゲーム、競プロ、数学

テクログに関する記事一覧

TOP