2010-07-12 4 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

ответ

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 вы можете также создать лямбды с

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

Смотрите PHP manual on Anonymous functions для дальнейшего использования.

+3

Для полноты, используя create_function таким образом, будет создавать функцию lamda в глобальном пространстве каждый раз, когда класс будет построен и останется в памяти без преимуществ сбора мусора (например, когда объект отключен). Он будет работать, но использовать с осторожностью. – webbiedave

+2

Для еще большей полноты 'create_function' не создает ничего подобного лямбда - это в основном прославленный' eval', который создает функцию с именем, так что никакая «реальная» функция не может конфликтовать. Если вам не нужна совместимость с PHP <5.3, его следует избегать, когда это возможно. – IMSoP

3

Вы можете использовать магический метод __call, чтобы использовать методы экземпляра времени выполнения.

class Foo 
{ 
    public function __call($name, $args) 
    { 
     if ($name == 'myFunc') { 
      // call myFunc 
     } 
    } 
} 
Смежные вопросы