PHP's magic method __call on subclasses

时光怂恿深爱的人放手 提交于 2019-12-05 02:37:43

__call() is only invoked when the function isn't otherwise found so your example, as written, is not possible.

It can't be done directly, but this is one possible alternative:

class SubFoo { // does not extend
    function __construct() {
        $this->__foo = new Foo; // sub-object instead
    }
    function __call($func, $args) {
        echo "intercepted $func()!\n";
        call_user_func_array(array($this->__foo, $func), $args);
    }
}

This sort of thing is good for debugging and testing, but you want to avoid __call() and friends as much as possible in production code as they are not very efficient.

One thing you can try is to set your functions scope to private or protected. When one private function is called from outside the class it calls the __call magic method and you can exploit it.

If you need to add something extra to the parent bar(), would this be doable?

class SubFoo extends Foo {
    function bar() {
        // Do something else first
        parent::bar();
    }
}

or is this just a question from curiosity?

What you could do to have the same effect is the following:

    <?php

class hooked{

    public $value;

    function __construct(){
        $this->value = "your function";
    }

    // Only called when function does not exist.
    function __call($name, $arguments){

        $reroute = array(
            "rerouted" => "hooked_function"
        );

        // Set the prefix to whatever you like available in function names.
        $prefix = "_";

        // Remove the prefix and check wether the function exists.
        $function_name = substr($name, strlen($prefix));

        if(method_exists($this, $function_name)){

            // Handle prefix methods.
            call_user_func_array(array($this, $function_name), $arguments);

        }elseif(array_key_exists($name, $reroute)){

            if(method_exists($this, $reroute[$name])){

                call_user_func_array(array($this, $reroute[$name]), $arguments);

            }else{
                throw new Exception("Function <strong>{$reroute[$name]}</strong> does not exist.\n");
            }

        }else{
            throw new Exception("Function <strong>$name</strong> does not exist.\n");
        }

    }

    function hooked_function($one = "", $two = ""){

        echo "{$this->value} $one $two";

    }

}

$hooked = new hooked();

$hooked->_hooked_function("is", "hooked. ");
// Echo's: "your function is hooked."
$hooked->rerouted("is", "rerouted.");
// Echo's: "our function is rerouted."

?>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!