2

私が取り組んでいるプロジェクトの DB エンティティ一般化のベースを動的に作成しようとしています。私は基本的に、これを拡張する任意のクラスのプロパティの一連の標準メソッドとツールを動的に作成したいと考えています。Python/Django で無料で入手できるツールによく似ています。

私はこの男からアイデアを得ました: http://www.stubbles.org/archives/65-Extending-objects-with-new-methods-at-runtime.html

そこで、上記の投稿で説明したように __call 関数を実装しました。

public function __call($method, $args) {
    echo "<br>Calling ".$method;
    if (isset($this->$method) === true) {
        $func = $this->$method;
        $func();
    }
}

get_object_vars を介してオブジェクトの public/protected プロパティを提供する関数があります。

public function getJsonData() {
    $var = get_object_vars($this);
    foreach($var as &$value) {
        if (is_object($value) && method_exists($value, 'getJsonData')) {
            $value = $value->getJsonData;
        }
    }
    return $var;
}

そして今、それらのためにいくつかのメソッドを作成したいと思います:

public function __construct() {
    foreach($this->getJsonData() as $name => $value) {
        // Create standard getter
        $methodName = "get".$name;
        $me = $this;
        $this->$methodName = function() use ($me, $methodName, $name) { 
            echo "<br>".$methodName." is called";
            return $me->$name; 
        };
    }
}

以下の「use」キーワードを指摘してくれた Louis H. に感謝します。これは基本的に、その場で無名関数を作成します。関数は呼び出し可能ですが、オブジェクトのコンテキスト内にはありません。「致命的なエラー: 保護されたプロパティにアクセスできません」というメッセージが表示されます

残念ながら、私は PHP バージョン 5.3 に縛られており、Closure::bind は除外されています。したがって、PHP でのクラス メソッドの遅延読み込みで提案されている解決策は、ここでは機能しません。

私はここで困惑しています...他に何か提案はありますか?

アップデート

簡潔にするために編集。

4

2 に答える 2

2

このように試してください(必要な変数をメソッドで使用できるようにする必要があります)

$this->$methodName = function() use ($this, $methodName, $name){ 
    echo "<br>".$methodName." is called";
    return $this->$$name; 
};

を介してオブジェクト コンテキストにアクセスできる必要があります$this

于 2013-01-25T13:46:11.330 に答える
0

上記の元の質問を更新する代わりに、同じ問題に苦しんでいる人のために、ここに完全な解決策を含めます。

まず、クロージャは実際のオブジェクトにアクセスできないため、クロージャ関数を作成するときに「use」宣言に実際の値を含める必要がありました(上記の元の__construct関数を参照)。

$value =& $this->$name;
$this->$methodName = function() use ($me, $methodName, &$value)  { 
    return $value; 
};

次に、__ callマジックメソッドは、クロージャ関数を呼び出すだけでなく、そこから出力を返す必要もありました。したがって、$ func()を呼び出す代わりに、$ func();を返します。

これでうまくいきました!:-)

于 2013-01-29T11:35:59.430 に答える