2010-07-12 27 views
8

創建實例方法,我希望能夠動態地創建一個類的構造函數中的實例方法如下所示:動態的PHP

class Foo{ 
    function __construct() { 
     $code = 'print hi;'; 
     $sayHi = create_function('', $code); 
     print "$sayHi"; //prints lambda_2 
     print $sayHi(); // prints 'hi' 
     $this->sayHi = $sayHi; 
    } 
} 

$f = new Foo; 
$f->sayHi(); //Fatal error: Call to undefined method Foo::sayHi() in /export/home/web/private/htdocs/staff/cohenaa/dev-drupal-2/sites/all/modules/devel/devel.module(1086) : eval()'d code on line 12 

這個問題似乎是在lambda_2函數對象是沒有得到在構造函數中綁定到$ this。

任何幫助表示讚賞。

+0

您可能想清除構造函數代碼中的錯誤。 – Gordon 2010-07-12 19:31:10

回答

18

您分配匿名函數到財產,但隨後嘗試調用一個方法屬性名。 PHP無法自動從屬性中取消引用匿名函數。下面的工作

class Foo{ 

    function __construct() { 
     $this->sayHi = create_function('', 'print "hi";'); 
    } 
} 

$foo = new Foo; 
$fn = $foo->sayHi; 
$fn(); // hi 

可以利用魔法__call方法來攔截無效的方法調用,以查看是否有控股的回調/匿名函數的性質,但:

class Foo{ 

    public function __construct() 
    { 
     $this->sayHi = create_function('', 'print "hi";'); 
    } 
    public function __call($method, $args) 
    { 
     if(property_exists($this, $method)) { 
      if(is_callable($this->$method)) { 
       return call_user_func_array($this->$method, $args); 
      } 
     } 
    } 
} 

$foo = new Foo; 
$foo->sayHi(); // hi 

隨着PHP5.3的,您也可以創建Lambdas

$lambda = function() { return TRUE; }; 

查看PHP manual on Anonymous functions作進一步參考。

+3

爲了完整起見,每當構造類時,使用這種方式的create_function將在全局空間中創建lamda函數,並保留在內存中而沒有垃圾回收的好處(例如,當對象未被設置時)。它會工作,但小心使用。 – webbiedave 2010-07-12 19:33:52

+2

爲了更加完整,'create_function'不會創建任何類似lambda的東西 - 它基本上是一個榮耀的'eval',它會創建一個名爲「true」的函數,以避免可能發生衝突。除非您需要與PHP <5.3兼容,否則應儘可能避免。 – IMSoP 2013-04-24 21:20:23

3

您可以使用__call魔術方法來使用運行時實例方法。

class Foo 
{ 
    public function __call($name, $args) 
    { 
     if ($name == 'myFunc') { 
      // call myFunc 
     } 
    } 
}