Подумав об этом, на самом деле это не ошибка.Но это определенно не интуитивно понятно.
<?php
class A
{
public function foo()
{
static::bar();
}
public function bar()
{
echo "bar()\n";
}
}
$a = new A();
$a->foo();
Это действительно, и вызывает bar ().Это не означает колл-бар статически.Это означает поиск текущего имени класса и вызов функции bar
, если она существует, независимо от того, является ли она статической или нет.
Чтобы пояснить немного подробнее: как вы думаете, parent::bar()
означает вызов статическогофункция называется bar()
?Нет, это означает вызов любой функции с именем bar()
.
Рассмотрим:
<?php
class A
{
function __call($name, $args)
{
echo "__call()\n";
}
static function __callStatic($name, $ags)
{
echo "__callStatic()\n";
}
function regularMethod()
{
echo "regularMethod()\n";
}
static function staticMethod()
{
echo "staticMethod()\n";
}
}
class B extends A
{
function foo()
{
parent::nonExistant();
static::nonExistant();
parent::regularMethod();
parent::staticMethod();
}
}
$b = new B();
$b->foo();
Метод parent::nonExistant()
вызывает A::__call()
, как и static::nonExistant()
.Вызов A::__callStatic()
для либо вызова будет одинаково действительным!У PHP нет возможности узнать, какой из них вы хотите назвать.Тем не менее, при разработке PHP дает __call
приоритет при вызове из этого вида контекста.
parent::regularMethod()
вызывает нестатическую функцию regularMethod()
.(Опять же, оператор ::
не означает «вызов этой статической функции».) Аналогично parent::staticMethod()
вызывает A::staticMethod()
, как и следовало ожидать.
Для решения вашей проблемы:
Youможно вручную вызвать self::__callStatic('foo')
в унаследованном классе.
Или в методе __call
класса A отфильтровать известный список и вызвать self::__callStatic
.
function __call($f, $a)
{
if ($f == 'foo')
return self::__callStatic($f, $a);
else
{
}
}
Это ужасно,но, по крайней мере, людям, которые расширяют класс, не нужно будет делать ничего особенного.