2009-10-08 84 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魔術方法,並且可以利用它。