2012-02-07 68 views
1

我有一些我想委託方法的PHP cruft。排序一個窮人的混合。PHP使用__get來調用方法?

基本上我想以下幾點:

<?php 

class Apprentice 
{ 
    public function magic() { 
     echo 'Abracadabra!'; 
    } 
} 

class Sourcerer // I work magic with the source 
{ 
    private $apprentice; 

    public function __construct(){ 
     $this->apprentice = new Apprentice(); 
    } 

    public function __get($key) { 
     if (method_exists($this->apprentice, $key)) { 
      return $this->apprentice->{$key}; 
     } 
     throw Exception("no magic left"); 
    } 
} 

$source = new Sourcerer(); 
$source->magic(); 
?> 

爲了不丟一Fatal error: Call to undefined method Sourcerer::magic() in .../test__get.php

回答

9
public function __call($name, $args) { 
    if (method_exists($this->apprentice, $name)) { 
     return $this->apprentice->$name($args); 
    } 
    throw Exception("no magic left"); 
} 

PS:使用__call爲方法作爲__get僅用於屬性。 是的,最好使用call_user_func_array,否則參數作爲數組提供給magic函數。

return call_user_func_array(array($this->apprentice, $name), $args); 
+0

This ++。 __call是你真正想要的東西。此外,如果您將來希望在靜態函數中使用這種功能,您可能需要調查__callStatic。 – Navarr 2012-02-07 01:35:28

+0

Ohhh ...我完全誤解了文檔,我認爲'__call()'是爲了調用一個實例,就好像它是一個函數,它是爲了實現'$ s = new S(); $ S();'。謝謝! – quodlibetor 2012-02-07 03:38:49

+0

@quodlibetor方法['__invoke'](http://php.net/manual/en/language.oop5.magic.php#object.invoke)用於調用實例,就像它是一個函數一樣。 – Wilt 2016-06-11 07:40:32

1

您的通話將改爲:

​​

而且,我相信__get()魔術方法適用於性能,而不是方法名。

最後,在你的實際__get()定義中,語法是錯誤的:它應該是throw new Exception('message');。我也會將其移至else子句,否則它將觸發每個呼叫,因爲它不在任何if/else或其他邏輯之外。

+0

你是正確的語法,而錯的'else'(該'if'有回報的必要性。 )但是查找鏈是我試圖避免的。 – quodlibetor 2012-02-07 03:40:52

3
  1. 實際調用的方法上apprentice,你必須實際調用它像這樣:

    return $this->apprentice->$key(); 
    
  2. 您使用$source->magic(),不調用__get方法。 __get用於像$source->magic這樣的可變訪問,但是$source->magic()是函數調用。如果你想要一個神奇的函數調用方法,那就是__call

2

更多類似__call,而不是__get你的情況:

class Sourcerer // I work magic with the source 
{ 
    private $apprentice; 

    public function __construct(){ 
     $this->apprentice = new Apprentice(); 
    } 

    public function __call($name, $arguments) { 
     if (method_exists($this->apprentice, $name)) { 
      return call_user_func_array(array($this->apprentice, $name), $arguments); 
     } 
     throw Exception("no magic left"); 
    } 
}