2012-02-07 34 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"); 
    } 
}