Я делал, некоторые тесты (для замены старого кода) __ вызывают волшебный метод, и я не уверен, что это - ошибка или нет:
Позволяет предполагают, что у нас есть класс:
class Calc {
function __invoke($a,$b){
return $a*$b;
}
}
Следующее возможно и работает без любой проблемы:
$c = new Calc;
$k = $c;
echo $k(4,5); //outputs 20
Однако, если я хочу иметь другой класс для хранения экземпляра того объекта, это не работает:
class Test {
public $k;
function __construct() {
$c = new Calc;
$this->k = $c; //Just to show a similar situation than before
// $this-k = new Calc; produces the same error.
}
}
Ошибка происходит, когда мы пытаемся назвать ее как:
$t = new Test;
echo $t->k(4,5); //Error: Call to undefined method Test::k()
Я знаю, что "решение" могло состоять в том, чтобы иметь функцию в классе Тест (названный k) для "переведения" вызова с помощью call_user_func_array, но это не изящно.
Я должен сохранить тот экземпляр в общем классе (в целях дизайна) и смочь назвать его как функцию от других классов... какое-либо предложение?
Обновление:
Я нашел что-то интересным (по крайней мере, в моих целях):
Если мы присваиваем "переменную класса" в локальную переменную, она работает:
$t = new Test;
$m = $t->k;
echo $m(4,5);
Когда вы выполняете $ test-> k ()
, PHP думает, что вы вызываете метод в экземпляре $ test
. Поскольку не существует метода с именем k ()
, PHP выдает исключение. Что вы пытаетесь сделать, так это заставить PHP вернуть общедоступное свойство k
и вызвать его, но для этого вы должны сначала присвоить k
переменной. Это вопрос разыменования.
Вы можете добавить волшебный метод __ call
в свой класс Test
, чтобы проверить, существует ли свойство с именем вызываемого метода, и вызвать его вместо этого:
public function __call($method, $args) {
if(property_exists($this, $method)) {
$prop = $this->$method;
return $prop();
}
}
Я оставляю добавление аргументы для обращения к вам.
Вы также можете проверить, является ли свойство is_callable
.
Но в любом случае вы можете сделать
$test->k();
PHP думает, что вы хотите вызвать метод k на экземпляре $t, когда вы это делаете:
$t->k(4, 5)
что вполне разумно. Вы можете использовать промежуточную переменную для вызова объекта:
$b = $t->k;
$b(4, 5);
См. также ошибка #50029, в которой описана ваша проблема.
Вы не можете использовать синтаксис метода (например, $ foo-> bar ()) для вызова замыканий или объектов с __invoke, поскольку движок всегда думает, что это вызов метода. Вы можете смоделировать это с помощью __call:
function __call($name, $params) {
if(is_callable($this->$name)) {
call_user_func_array($this->$name, $params);
}
}
, но он не будет работать как есть.