我的情况最好用一些代码来描述:
class Foo {
function bar () {
echo "called Foo::bar()";
}
}
class SubFoo extends Foo {
function __call($func) {
if ($func == "bar") {
echo "intercepted bar()!";
}
}
}
$subFoo = new SubFoo();
// what actually happens:
$subFoo->bar(); // "called Foo:bar()"
// what would be nice:
$subFoo->bar(); // "intercepted bar()!"
我知道我可以通过重新定义子类中的bar()
(和所有其他相关方法)来实现这一点,但就我的目的而言,__call
函数会很好可以处理它们。它只会使很多更整洁,更易于管理。
这可以在PHP中使用吗?
答案 0 :(得分:14)
__call()
仅在未找到该函数时调用,因此无法执行您的示例。
答案 1 :(得分:2)
不能直接完成,但这是一种可能的选择:
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);
}
}
这类事情适合调试和测试,但您希望在生产代码中尽可能避免使用__call()
和朋友,因为它们效率不高。
答案 2 :(得分:1)
您可以尝试的一件事是将您的功能范围设置为私有或受保护。当从类外部调用一个私有函数时,它调用__call魔术方法,你可以利用它。
答案 3 :(得分:0)
如果您需要在父栏()中添加额外的内容,这是否可行?
class SubFoo extends Foo {
function bar() {
// Do something else first
parent::bar();
}
}
或者这只是好奇心的问题?
答案 4 :(得分:0)
您可以采取以下措施来实现相同的效果:
<?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."
?>