Поскольку PHP 5.3 поддерживает замыкания, вы можете динамически определять методы экземпляров как переменные, содержащие замыкания:
$class->foo = function (&$self, $n) {
print "Current \$var: " . $self->var . "\n";
$self->var += $n;
print "New \$var: " .$self->var . "\n";
};
Взяв $self
(вы не можете использовать $this
вне контекста объекта) в качестве ссылки (&
), вы можете изменить экземпляр.
Однако возникают проблемы при обычном вызове функции:
$class->foo(2);
Вы получаете фатальную ошибку. PHP думает, что foo
- это метод $class
из-за синтаксиса. Кроме того, вы должны передать экземпляр в качестве первого аргумента.
К счастью, есть специальная функция для вызова функций по имени call_user_func
:
call_user_func($class->foo, &$class, 2);
# => Current $var: 0
# => New $var: 2
Просто не забудьте поставить &
перед переменной экземпляра.
Что еще проще, если вы используете магический метод __call
:
class MyClass {
public function __call ($method, $arguments) {
if (isset($this->$method)) {
call_user_func_array($this->$method, array_merge(array(&$this), $arguments));
}
}
}
Теперь вы можете позвонить $class->foo(2)
вместо этого. Магический метод __call
перехватывает вызов неизвестного метода и вызывает замыкание в переменной $class->foo
с тем же именем, что и вызываемый метод.
Конечно, если $class->var
было закрыто, замыкание в переменной $class->foo
не сможет получить к нему доступ.