2009-10-08 173 views
9

我的情况是最好的一段代码描述但是为了我的目的,如果__call函数可以处理它们会很好。它只会让事情变得更加易于管理。PHP关于子类魔术方法__call

这是可能的PHP?

回答

13

__call()仅在函数未被找到时才被调用,因此您的示例不可写。

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()和朋友尽可能在生产代码,因为它们效率不高。

+0

这个。你需要遵循Facade模式。有一个包装类“拥有”你想覆盖所有这些功能的对象。使用__call()根据需要传递方法,根据需要进行任何额外的工作。除非您的代码经常被调用,并且您的应用程序受CPU限制(几乎从不是这种情况),否则不要为性能付出代价 - 编程人员在决定进行这种权衡时几乎总是比性能更重要。 – 2013-02-22 04:33:48

0

如果你需要添加额外的东西到父栏(),这是可行的吗?

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

或者这只是一个好奇心的问题?

+1

这个问题源于父类可能有一堆函数的事实,我不想在子类中重复它们,只是为了应用相同的行为('//先做别的事情'部分)给他们所有人 – nickf 2009-10-08 02:51:32

+0

@nickf绝对,这在我看来是非常必要的东西,我不明白为什么它不在PHP中。 – 2011-08-24 13:05:24

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." 

?> 
1

有一件事你可以尝试是设置功能范围,私有或保护。当从外部调用一个私有函数时,它会调用__call魔术方法,并且可以利用它。