在PHP中动态创建实例方法

Aar*_*ron 8 php oop dynamic

我希望能够在类的构造函数中动态创建实例方法,如下所示:

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 
Run Code Online (Sandbox Code Playgroud)

问题似乎是lambda_2函数对象没有在构造函数中绑定到$ this.

任何帮助表示赞赏.

Gor*_*don 18

您将匿名函数分配给属性,但然后尝试使用属性名称调用方法.PHP无法从属性中自动取消引用匿名函数.以下将有效

class Foo{

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

$foo = new Foo;
$fn = $foo->sayHi;
$fn(); // hi
Run Code Online (Sandbox Code Playgroud)

您可以利用魔术__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
Run Code Online (Sandbox Code Playgroud)

从PHP5.3开始,您还可以创建Lambdas

$lambda = function() { return TRUE; };
Run Code Online (Sandbox Code Playgroud)

有关进一步的参考,请参阅匿名函数的PHP手册.

  • 为了完整起见,以这种方式使用create_function将在每次构造类时在全局空间中创建一个lamda函数,并且将保留在内存中而没有垃圾收集的好处(例如,当对象未设置时).它会起作用,但要小心使用. (3认同)
  • 为了更加完整,`create_function`不会创建像lambda这样的东西 - 它基本上是一个美化的`eval`,它创建了一个名为"没有"真正的"函数"可能发生冲突的函数.除非您需要与PHP <5.3兼容,否则应尽可能避免. (2认同)