2015-06-15 1 views
0

Как мне позвонить $greet внутри этого класса? Я использую PHP 5.5.4.Как вы используете анонимную функцию внутри класса в PHP?

<?PHP 
class Model 
{ 
    public $greet = function($name) 
    { 
     printf("Hello %s\r\n", $name); 
    }; 
} 

$test = new Model(); 
$test->greet('World'); 
$test->greet('PHP'); 
?> 

Parse error: syntax error, unexpected '$greet' (T_VARIABLE), expecting function (T_FUNCTION) 

попытался Также это,

$test = new Model(); 
call_user_func($test->greet('World')); 
call_user_func($test->greet('PHP')) 

Анонимная функция отлично работает вне класса (прямо из manual).

<?php 
$greet = function($name) 
{ 
    printf("Hello %s\r\n", $name); 
}; 

$greet('World'); 
$greet('PHP'); 
?> 

EDIT: Я вынул знаки доллара, на мой звонок (я поймал его так же, как ответ начал катиться в это не помогло,

call_user_func($test->greet('World')); 
call_user_func($test->greet('PHP')); 

EDIT:.

class Model 
{ 
    public $greet; 
    function __construct() 
    { 
     $this->greet = function($name) 
     { 
      printf("Hello %s\r\n", $name); 
     }; 
    } 
} 

$test = new Model(); 
$test->greet('johnny'); 

Теперь я получаю,

Fatal error: Call to undefined method Model::greet() 

ответ

1

Тот факт, что вы называете greet делает PHP рассматривать его как функция, а не свойство. Вы можете иметь одно и то же имя для свойства и метода в PHP, поэтому различие имеет значение.

Что вы можете сделать в качестве обходного пути, используйте метод магии __call(). Он поймает вызов неопределенного метода greet.

class Model 
{ 
    public $greet; 
    function __construct() 
    { 
     $this->greet = function($name) 
     { 
      printf("Hello %s\r\n", $name); 
     }; 
    } 

    function __call($method, $args) 
    { 
     if (isset($this->$method) && $this->$method instanceof \Closure) { 
      return call_user_func_array($this->$method, $args); 
     } 

     trigger_error("Call to undefined method " . get_called_class() . '::' . $method, E_USER_ERROR); 
    } 
} 

$test = new Model(); 
$test->greet('johnny'); 

Обновление для PHP7

В PHP7 метод __call() больше не нужно вызвать закрытие связанных со свойствами, из-за Uniform Variable Syntax. Это позволит вам добавлять круглые скобки вокруг любого кода, как и в арифметике.

class Model 
{ 
    public $greet; 
    function __construct() 
    { 
     $this->greet = function($name) 
     { 
      printf("Hello %s\r\n", $name); 
     }; 
    } 
} 

$test = new Model(); 
($test->greet)('johnny'); 
+0

Зачем вам нужно назначать функцию в конструкторе или каком-либо другом методе? Это не сработает, если вы этого не сделаете (для меня). – johnny

+0

Вы имеете в виду 'Parse error' из вашего первого примера? Использование ключевого слова 'function' в определении класса означает создание метода, а не анонимную функцию. –

+0

Нет, я имею в виду, когда вы назначаете анонимную функцию переменной. Это нужно сделать в функции (или конструкторе). Он не может быть просто переменной-членом. – johnny

2

Вы не можете INITI alize объектные переменные с результатами выражений. Разрешены только статические/постоянные значения. например

class foo { 
    public $bar = 1+1; // illegal - cannot use an expression 
    public $baz = 2; // valid. '2' is a constant 
} 

Вы должны были бы сделать:

class foo { 
    public $bar; 
    function __construct() { 
     $this->bar = function() { .... } 
    } 
} 

И на самом деле вызвать замыкание, согласно this answer:

$x = new foo() 
$x->bar->__invoke(); 
+0

Как я могу назвать его вне класса? Должен ли я обернуть его в другую функцию, которая возвращает значение, как обычно делает любая старая переменная? Я пробовал разные способы, но они не работают. – johnny

+0

, если вы построите замыкание в конструкторе, '$ bar' будет« указывать »на замыкание к моменту возврата вызова' new'. поэтому '$ x = new foo(); $ x-> bar(); 'должен работать так, как ожидалось. –

+0

Не могли бы вы рассказать мне, что я делаю неправильно в своем Редактировании выше? Изменить: Извините. Я забыл внести изменения! – johnny