2

私が取り組んでいる傍受クラスをモックアップしていました。アイデアは、Intercept クラスを介してクラスをインスタンス化し、そのオブジェクトをインターセプトするクラスであるかのように使用することです。クラスが呼び出されるたびに、指定されたコールバックが実行されます。コードは次のとおりです。

<?php
class Intercept {

    protected $class = null;
    protected $callback = null;

    public function __construct($class, $callback = null) {

        $this->class = new $class();
        $this->callback = $callback;
    }

    protected function run_callback() {

        $this->callback();
    }

    public function __get($name) {

        $this->run_callback();
        return $this->class->$name;
    }

    public function __set($name, $value) {

        $this->run_callback();      
        return $this->class->$name = $value;
    }

    public function __isset($name) {

        $this->run_callback();
        return isset($this->class->$name);
    }

    public function __unset($name) {

        $this->run_callback();
        unset($this->class->$name);
    }

    public function __call($method, $args) {

        $this->run_callback();
        return call_user_func_array(array($this->class, $method), $args);
    }

    public function __toString() {

        $this->run_callback();
        return $this->class;
    }

    public function __invoke() {

        $this->run_callback();
        return $this->class();
    }
}

class test {
    public function hello() { 
        return 'world'; 
    }
}

$closure = function() {
    echo 123;
};

$test=new Intercept('test', $closure);
echo $test->hello();

上記のコードを実行すると、「world123」が表示されます。しかし、私には見えない何らかの奇妙な理由で、タイムアウトになってしまいます。ローカル マシンとオンラインのさまざまな php 5.4 テスター サイトで試してみました。同じことが起こります。run_callback() メソッドで実行中のクロージャー ($this->callback()) に絞り込みました。$this->callback() を削除するだけで問題なく動作します。なぜこうなった?

編集、この質問を書いているときに、代わりに次のことを理解しました:

$this->callback();

これを行うと、タイムアウトが停止します。

$closure = $this->callback;
$closure();

クラス プロパティから直接クロージャを実行しようとするたびに __call メソッドが呼び出されるようです。これは予期された動作ですか、それとも PHP のバグに遭遇したのでしょうか?

4

1 に答える 1

4

関数呼び出しスタックに無限ループがあるためです。あなたがするとき

$this->callback();

メンバー関数を実行しようとしてcallback()いますが、存在しないため実行され、再__call()試行され、存在しないため実行されます。callback()__call()

次の行に沿って何かを使用する必要があります。

call_user_func( $this->callback);

または、編集したように、これも機能します。

$closure = $this->callback;
$closure();

うまくいけば、これで何が起こっているのかが明らかになります。リソース (この場合は時間) が不足しているため、タイムアウトが発生しています。根本的な問題は無限ループです。

于 2013-02-12T02:29:54.333 に答える