Особенности магического метода __call в PHP
Не всё работает так, как заявлено в документации
Те, кто хорошо знают PHP5, наверняка знакомы или хотя бы раз использовали такой мощный инструмент, как магические методы.
Один из методов, __call(), согласно документации используется при попытке вызова недоступного метода в контексте объекта.
Иными словами, в следующем фрагменте кода
class A {
public function __call($method, $params)
{
print "Attempt to call {$method}\n";
}
}
$a = new A();
$a->someMethod();
?>
будет вызван магический метод A::__call("someMethod", array()), который напечатает
С несуществующими методами всё ясно, но в документации упоминается слово «недоступные» (inaccessible).
А с недоступными методами, к сожалению, не всё так гладко. Рассмотрим пример:
class A {
public function get()
{
return array(&$this, 'test');
}
public function __call($method, $params)
{
if (true == method_exists($this, $method)) {
call_user_func_array(array(&$this, $method), $params);
}
}
protected function test()
{
echo "It makes me money and that's all right\n";
}
}
$a = new A();
$callback = $a->get();
call_user_func($callback);
?>
Метод A::test() является доступным в контексте класса A, но недоступным в контексте объекта $a. Следуя документации, ожидаемым результатом был бы вызов A::test() из A::__call(). Но в действительности всё не так, как на самом деле:
А метод __call() даже не вызывается.
В принципе, я не обратил бы на это внимание, если бы магические методы __get()/__set()/__isset()/__unset() работали точно так же. Но я знаю, что это не так:
class A
{
private $x;
public function __get($name)
{
print $name . "\n";
return null;
}
}
$a = new A();
$a->x;
?>
В этом случае, хотя $a->x и недоступен в контексте объекта $a, метод A::__get() будет вызван.
Я не знаю, считать ли политику (не)вызова __call() в PHP ошибкой или нет, ясно одно: подобное поведение не согласуется с политикой вызовов других магических методов.
Июн
2009
Комментарии к статье «Особенности магического метода __call в PHP» (3) »
Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.
Оставить комментарий к записи «Особенности магического метода __call в PHP»
गते गते पारगते पारसंगते बोधि स्वाहा
Меня зовут Владимир, я программист-фрилансер, специализирующийся на Web-программировании и програмировании под Linux.
По совместительству занимаюсь администрированием LAMP/LNMP-серверов и техническим переводом.


Исправлено в PHP 5.3
Проверил ваш пример с __call на версии пхп 5.2.12 все работает, ошибок не возникает.
В каких версиях пхп у вас были ошибка
Warning: call_user_func(A::test): First argument is expected to be a valid callback in test-visibility.php on line 23
?
Исправлено в 5.2.9 и 5.3.0.