2013-07-01 2 views
2

У меня есть некоторые путаницы! Я простой класс, как указано нижеPhp - динамически добавленный метод не вызывается

class MyClass { 
    public $bar; 
} 

Тогда я сделал экземпляр

$cls = new MyClass; 

Тогда я присвоено значение моей общественной собственности $bar снаружи класса

$cls->bar='Bar'; 

Затем я добавил новое публичное имущество $baz и присвоенное ему значение извне класса

$cls->baz='Baz'; 

Затем я добавил новую общественную собственность $showBar и присваивается значение к нему извне класса и на этот раз значения является анонимной функцией

$cls->showBar = function(){ 
    return $this->bar; 
}; 

Тогда я свалил $cls используя var_dump($cls); экземпляр и выход

object(MyClass)[10] 
    public 'bar' => string 'Bar' (length=3) 
    public 'baz' => string 'Baz' (length=3) 
    public 'showBar' => 
    object(Closure)[11] 

Кажется, что все публичные свойства доступны, которые я добавил в том числе функции anonymous, а затем я сделал

echo $cls->bar; // Bar 
echo $cls->baz; // Baz 
echo $cls->showBar(); // error 

Публичная собственность showbar доступна в класса (var_dump показывает его), но когда я вызываю функцию он говорит

Fatal error: Call to undefined method MyClass::showBar() in D:\xampp\htdocs\phpTutorialInfo\bind\bindtoCls.php on line 234

Возникает вопрос: Можно добавлять новые свойства после инициализация (отлично работает со скалярным значением), а также showbar кажется доступным тогда почему не может Php признать это, и если это потому, что это значение является анонимной функцией, то почему оно доступно на выходе var_dump, включая функцию эльф и почему Php позвольте мне назначить значение (анонимная функция), оно должно было вызвать ошибку, когда я пытался присвоить значение showbar? Возможно ли это вообще?

+0

Я думаю, что путь вы вызываете функцию Showbar(), он не может думать о $ это как являющийся объектом $ cls. Получили ли вы фактическое сообщение об ошибке? Проводка может помочь осветить вещи. – murftown

+0

Возможный дубликат [Лямбда-функции в PHP не являются логическими] (http://stackoverflow.com/questions/2080248/lambda-functions-in-php-arent-logical) – outis

ответ

4

Вы не можете вызвать функцию таким образом. Это связано с тем, что PHP позволяет иметь переменные функции с тем же именем в классе. Если вы используете оператор функции () PHP будет изучать только список функций и не смотреть на переменные, которые являются закрытиями.

На PHP5.4 решение может выглядеть следующим образом:

class MyClass { 

    public function __call($fname, $args) { 
     // bind the `this` scope to use 
     $cl = $this->{$fname}->bindTo($this); 
     // call the function and pass args to it 
     return call_user_func_array($cl, $args); 
    } 

} 

Пример:

$obj = new MyClass(); 
$obj->func = function() { 
    echo 'We are in ' . get_class($this); 
}; 

$obj->func(); // We are in MyClass 

Вы можете проверить это here

+0

Извините, это не помогло, m using 'Php 5.4': O –

+0

** Извините ** это была синтаксическая ошибка. Я исправил его – hek2mgl

+0

'echo $ cls-> showBar -> __ invoke();' не будет работать, поскольку он устанавливает закрытие и использует '$ this', когда из контекста, я считаю, что метод магии' __call' может помочь. –

2

Вы можете использовать call_user_func. Пример:

<?php 
class MyClass { 
    public $bar; 
} 
$cls = new MyClass; 
$cls->bar='Bar'; 
$cls->baz='Baz'; 
$cls->showBar = function() use ($cls) { 
    return $cls->bar; 
}; 

echo call_user_func($cls->showBar); // Bar 
?> 

Вы можете определить магический метод __call так что это может быть возможно return $this->bar вместо прохождения $cls в замыкании.

+0

Это будет работать (я уже тестировал его), но '$ this' не применяется внутри закрытия. Я просто пытаюсь имитировать «прототип» 'JavaScript', если это вообще возможно, но спасибо за ваш ответ. –

+0

Дело в том, что это решение ... вы просто «изобретаете колесо», когда хотите просто получить доступ к '$ cls-> bar'; хотя это только для этого примера. Ваш пробег может отличаться. –

+0

Я просто пытаюсь добавить методы после инициализации объекта, используя 'Closure'. –

3

Вы не можете динамически добавлять метод в PHP. Вы сделали добавление настраиваемого свойства, которое является функцией. Но это не делает его методом. Для того, чтобы проиллюстрировать разницу, вы можете создать класс, со свойством & методом с тем же именем:

class A { 
    public $test = 42; 
    public test() { return 43; } 
} 

$a = new A; 
$a->test === 42; 
$a->test() === 43; 
+0

Закрытие может быть методом как свойство. –

+2

Нет, закрытие может быть привязано к объекту, но это не делает их методами, т. Е. Вы не можете называть их как '$ object-> closAsProperty()' – pozs

Смежные вопросы