風柳メモ

ソフトウェア・プログラミング関連の覚書が中心

PHPは難しい…配列にキーが存在するかはisset()じゃ厳密には判らないのね

これも今更な話なのだが、いままでPHPである連想配列$fooに'bar'というキーが存在するかを調べるのに、

if (isset($foo['bar'])) {
    // キーが存在した場合の処理
}

とやっていたんだけれど、厳密にはこれじゃだめだったんだね…。

説明

bool isset ( mixed $var [, mixed $... ] )

変数がセットされており、それが NULL でないことを調べます。

変数が、 unset() により割当を解除された場合、 何も値が設定されていない状態になります。 NULLに設定されている変数を調べた場合、 isset() はFALSEを返します。 NULLバイト("\0")はPHPの定数 NULLと等価ではないことにも注意してください。

PHP: isset - Manual

期待していたのは、「割り当て解除時」にのみ false が返り、他は true というものだったのだが、違ったわけだ。NULL のみ特別扱い(''や 0 や "\0" がセットされていたら true)。
issetって名前なんだから、NULLがセットされていても true 返せよ……マニュアルに書いてある仕様通り、と言われれば、ぐうの音も出ないが。

ちなみに、未割当の(解除された)変数へのポインタを代入した参照渡しをした変数を引数にしても false が返る。

$b=1; unset($b); $a=&$b; var_dump(isset($a)); // bool(false)
$b=null; var_dump(isset($a)); // bool(false)
$b=1; var_dump(isset($a)); // bool(true)

というか、これに類似した処理を行っている箇所の動きがおかしかったので、上記の事に気が付いた。

ということで、想定している動作をさせようとすると、

if (array_key_exists('bar', $foo)) {
    // キーが存在した場合の処理
}

と書く必要がある、ということ。