🈳
定義されていないプロパティをemptyで判定して頭を抱えた話
はじめに
こんなクラスがあったとします。
class Foo {
private array $bar;
public function __construct()
{
$this->bar = [
'test' => 'test',
];
}
public function __get(string $name): string
{
return isset($this->bar[$name]) ? $this->bar[$name] : '';
}
}
変数 $bar
はprivateなので外から直接触れませんが、Foo
で定義されていないプロパティへのアクセスがあった場合、 $bar
のキーから探して、あれば値を返却し、なければ空文字列を返却する、となっています。
では、以下を実行してみます。
$foo = new Foo();
echo $foo->test;
echo PHP_EOL;
if (empty($foo->test)) {
echo 'Empty';
} else {
echo 'Exists';
}
結果は。。
test
Empty
普通に考えて、 $foo->test
は $bar['test']
を参照するので、echo $foo->test
は test
を出力するのはわかります。
しかし、 empty($foo->test)
で true を得るのがよくわかりません。あるのに無い?
なぜこうなるのか?
PHPのマニュアルには以下のような記述があります。
変数が存在しなくても警告は発生しません。 つまり、empty() は本質的に !isset($var) || $var == false と同じことを簡潔に記述しているだけです。
定義されていないプロパティ test
に対して isset
を使用する場合は、__isset
にてオーバーロードする必要が出てきます。Fooクラスには、__isset
が宣言されていないため、isset
では定義されていない test
が存在しないと判断されるようです。
つまり、!isset($foo->test) === true
となるため、empty($foo->test) === true
となるとのことでした。
以下をFooクラスに追加すれば期待通りの出力を得られそうです。
public function __isset(string $name): bool
{
return isset($this->bar[$name]);
}
test
Exists
おわりに
empty、難しいのであんまり使いたくない。。
Discussion