downing1988 2013-02-12 02:24
浏览 60
已采纳

PHP 5.4次调用关闭

I was just mocking up an intercept class I am working on. Idea is you instantiate the class through the Intercept class and then use that object as if it was the class you are intercepting. A specified callback is then run every time the class gets called. Here is the code:

<?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();

Now, running the code above should display 'world123'. But for some strange reason which I cannot see, it ends up timing out. I tried it on my local machine, and on various php 5.4 tester sites online. Same thing happens. I have narrowed it down to the closure being run ($this->callback()) in the run_callback() method. If i just remove the $this->callback(), it works fine. Why is this happening?

Edit, while I was writing this question, I figured out that instead of:

$this->callback();

Doing this will stop the timeout:

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

It seems that the __call method gets called everytime I try to run the closure directly from the class properties. Is this expected behaviour or have I stumbled apon a PHP bug?

  • 写回答

1条回答 默认 最新

  • dongma7796 2013-02-12 02:29
    关注

    Pretty sure it's because you have an infinite loop with the function call stack. When you do

    $this->callback();
    

    You're trying to execute the member function callback(), which doesn't exist, so __call() gets executed, which tries callback() again, which doesn't exist, so __call() gets executed, and so on and so forth.

    You should be using something along the lines of:

    call_user_func( $this->callback);
    

    Or, like you've edited, this will work too:

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

    Hopefully this clears up what is happening. The timeout is just occurring because you're running out of resources (in this case, time). The underlying problem is the infinite loop.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改