Я использую следующий класс для имитации анонимных объектов в PHP:
class AnonymousObject { protected $methods = array(); public function __construct(array $options) { $this->methods = $options; } public function __call($name, $arguments) { $callable = null; if (array_key_exists($name, $this->methods)) $callable = $this->methods[$name]; elseif(isset($this->$name)) $callable = $this->$name; if (!is_callable($callable)) throw new BadMethodCallException("Method {$name} does not exist"); return call_user_func_array($callable, $arguments); } }
( https://gist.github.com/Mihailoff/3700483 )
Теперь, пока объявленные функции стоят сами по себе, все работает нормально, но всякий раз, когда я пытаюсь вызвать одну функцию из другой, как это …
$anonymous = new AnonymousObject(array( "foo" => function() { $this->bar(); }, "bar" => function() { } ));
то, конечно, я получаю Fatal error: Using $this when not in object context
Есть ли способ обойти эту проблему?
Вы можете использовать метод bind () или bindTo () экземпляра Closure, который представляет анонимную функцию.
<?php class AnonymousObject { protected $methods = array(); public function __construct(array $options) { $this->methods = $options; } public function __call($name, $arguments) { $callable = null; if (array_key_exists($name, $this->methods)) $callable = $this->methods[$name]; elseif(isset($this->$name)) $callable = $this->$name; if (!is_callable($callable)) throw new BadMethodCallException("Method {$name} does not exists"); $callable = $callable->bindTo($this); return call_user_func_array($callable, $arguments); } } $anonymous = new AnonymousObject(array( "foo" => function() { echo 'foo'; $this->bar(); }, "bar" => function() { echo 'bar'; } )); $anonymous->foo();
(пример не совсем прав, поскольку он будет работать только с анонимными функциями, а не со всеми другими вызываемыми () альтернативами, такими как, например, часть $ this-> name)
печатает foobar
.