3

__getマジック メソッドを利用して、存在しないプロパティにアクセスするとどうなるかを定義します。

したがって、$property->bla存在しない場合は取得しnullます。

return (isset($this->$name)) ? $this->$name : null;

しかし、それが存在しないことが$property->bla->blaわかっている場合は、エラーをスローしてキャッチしたいと考えています。$property->bla

以下でreturn (isset($this->$name)) ? $this->$name : null;このエラーが発生しますが、

<b>Notice</b>:  Trying to get property of non-object in...

だから私throw and catchは自分のクラスでエラーを使用し、

クラスプロパティ {

public function __get($name)
{
    //return (isset($this->$name)) ? $this->$name : null;

    try {
        if (!isset($this->$name)) {
          throw new Exception("Property $name is not defined");
        }
        return $this->$name;
      }
      catch (Exception $e) {

        return $e->getMessage(); 
      }
}

}

しかし、 forの代わりにthrowエラーメッセージが表示されるため、結果は私が望むものではありません。("Property $name is not defined")null$property->bla

、などに対してのみエラー メッセージをスローするようにするにはどうすればよいですか?$property->bla->bla$property->bla->bla->bla

4

2 に答える 2

2

できません。

関数の範囲内では、__get()についてしか知りません$property->blah。それが言語の機能であるため、その後に何が続くかはわかりません。

の評価の順序に注意してください$foo = $property->blah->blah2->blah3

  1. $temp1 = $property->blah;
  2. $temp1 = $temp1->blah2;
  3. $foo = $temp1->blah3;

もちろん$temp1は架空のものですが、これは本質的にそのステートメントの実行で起こることです。あなたの__get()呼び出しは、そのリストの最初の呼び出しのみを認識し、それ以上は認識しません。あなたができることは、呼び出し側でエラーを処理することproperty_exists()ですnull

$temp = $property->blah;
if( $temp === null || !property_exists( $temp, 'blah2')) {
    throw new Exception("Bad things!");
}

property_exists()で返されたオブジェクト$tempも に依存している場合は失敗することに注意してください。ただし__get()、OP では明確ではありませんでした。

于 2012-11-14T16:57:27.470 に答える
1

実際、$property->foo->barクラス$propertyに魔法の __get メソッドがある場合、fooプロパティのみを検証し、それに対してのみエラーをスローできます。

ただしfoo、同じクラス (または同じマジック__getメソッドを持つ類似のクラス) のインスタンスでもある場合は、プロパティを検証barして次のエラーをスローすることもできます。

例えば:

class magicLeaf {
    protected $data;
    public function __construct($hashTree) {
        $this->data = $hashTree;
    }
    // Notice that we returning another instance of the same class with subtree
    public function __get($k) {
        if (array_key_exists($k, $this->data)) {
             throw new Exception ("Property $name is not defined");
        }
        if (is_array($this->data[$k])) { // lazy convert arrays to magicLeaf classes
            $this->data[$k] = new self($this->data[$k]);
        }
        return $this->data[$k];
    }
 }

そして今、それを使用する単なる例:

$property = new magicLeaf(array(
    'foo' => 'root property',
    'bar' => array(
        'yo' => 'Hi!',
        'baz' => array(
            // dummy
        ),
    ),
));
$property->foo; // should contain 'root property' string
$property->bar->yo; // "Hi!"
$property->bar->baz->wut; // should throw an Exception with "Property wut is not defined"

これで、ほぼ思いどおりに作成する方法がわかります。

次に、あなた__constructと魔法の__getメソッドを少し変更し、新しいパラメーターを追加して、各レベルでの位置を確認します。

...
    private $crumbs;
    public function __construct($hashTree, $crumbs = array()) {
        $this->data = $hashTree;
        $this->crumbs = $crumbs;
    }
    public function __get($k) {
        if (array_key_exists($k, $this->data)) {
             $crumbs = join('->', $this->crumbs);
             throw new Exception ("Property {$crumbs}->{$name} is not defined");
        }
        if (is_array($this->data[$k])) { // lazy convert arrays to magicLeaf classes
            $this->data[$k] = new self($this->data[$k], $this->crumbs + array($k));
        }
        return $this->data[$k];
    }
...

私はそれがあなたが望むように動作するはずだと思います。

于 2013-03-27T23:49:19.170 に答える