15

件名、特にthis oneについて多くのSOの質問がありますが、それは私には役に立ちません。

property_existsと の間にはあいまいさがあるissetので、質問する前に指摘しておきます。

property_exists

property_existsは、オブジェクトに値を確認せずにプロパティが含まれているかどうかをチェックし、その可視性のみを確認します。

したがって、次の例では:

<?php

class testA
{
  private $a = null;
}
class testB extends testA
{
}

$test = new testA();
echo var_dump(property_exists($test, 'a')); // true

// parent's private property becomes invisible for its child

$test = new testB();
echo var_dump(property_exists($test, 'a')); // false

設定

issetは、値がfalse に等しい場合は is が設定されていないことを考慮して、プロパティに値が存在するかどうかをチェックしますnull

<?php

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

$var = '';
echo var_dump(isset($var)); // true

$var = false;
echo var_dump(isset($var)); // true

$var = 0;
echo var_dump(isset($var)); // true

$var = '0';
echo var_dump(isset($var)); // true

issetproperty_exists魔法のように追加されたプロパティに対するとの動作

プロパティにはnull値が存在する可能性があるため、__isset魔法の方法を使用してプロパティが存在するかどうかを知ることはできません。property_existsまた、魔法のメソッドを使用してプロパティが追加されるため、使用できません。

これはサンプルですが、これは単なるサンプルです。私のアプリでは、魔法のように設定されたプロパティが object の外部に格納されているためです。

class test {

    private $data = array();

    public function __get($key) {
        echo "get $key\n";
        return array_key_exists($key, $data) ? $data[$key] : null;
    }

    public function __set($key, $value) {
        echo "set $key = $value\n";
        $this->data[$key] = $value;
    }

    public function __isset($key) {
       echo sprintf("isset $key ( returns %b )", isset($this->data[$key]));
       return isset($this->data[$key]);
    }

}

$test = new test();
$test->x = 42;
isset($test->x); // 1

$test->y = null;
isset($test->y); // 0
property_exists($test, 'y'); // 0

だからここに私の質問があります:

property_exist魔法のように追加されたプロパティで実装する魔法のメソッドまたは SPL インターフェイスはありますか?

4

2 に答える 2

7

魔法のメソッドを使用して property_exists() の機能を変更する方法があるとは思いません。PHPで使用可能なマジック メソッドのリストを次に示します。ただし、好きなロジックを使用するように isset() を変更できるはずです。

class test {

    private $data = array();

    public function __get($key) {
        echo "get $key\n";
        return array_key_exists($key, $this->data) ? $this->data[$key] : null;
    }

    public function __set($key, $value) {
        echo "set $key = $value\n";
        $this->data[$key] = $value;
    }

    public function __isset($key) {
       echo sprintf("isset $key ( returns %b )", array_key_exists($key, $this->data));
       return array_key_exists($key, $this->data);
    }

}

$test = new test();
$test->x = 42;
isset($test->x); // 1

$test->y = null;
isset($test->y); // 1

これにより、魔法の方法でその機能をオーバーライドすることにより、 isset と null の (厄介な) 問題が効果的に修正されます。ただし、__isset() 内で isset() を使用する代わりに、array_key_exists を使用します (予想どおり null を処理します)。したがって、null 値が設定されている場合、__isset() は期待される結果を返します。

これには欠点があります。つまり、オーバーライドされた機能は、デフォルトの isset() 機能と同じ結果を生成しません。したがって、このオブジェクトを他の (おそらく stdClass) オブジェクトと共に透過的に使用する必要がある場合、 isset() は、このクラスのオブジェクトの null 値に対して true を返し、通常のオブジェクトの null 値に対して false を返します。

ニーズによっては、これが実行可能なソリューションである場合とそうでない場合があります。上記の問題が妨げになる場合は、別のオプションとして、keyIsSet() プロパティを使用してインターフェイスを定義し、そのインターフェイスをテスト対象のすべてのオブジェクトに適用することもできます。次に、isset($obj->$key) ではなく $obj->keyIsSet('key') を使用します。それほどエレガントではありませんが、少し良くなりました。

于 2014-01-13T22:22:44.970 に答える