Особенности магического метода __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 ошибкой или нет, ясно одно: подобное поведение не согласуется с политикой вызовов других магических методов.
Связанные записи
Автор: Vladimir; опубликовано в: PHP; метки: PHP, магические методы, ООПИюнь
2009


Меня зовут Владимир, я программист-фрилансер, специализирующийся на Web-программировании и програмировании под Linux.
По совместительству занимаюсь администрированием LAMP/LNMP-серверов и техническим переводом.






Исправлено в PHP 5.3