Как заставить __callStatic для неизвестных статических методов, даже если существует метод экземпляра с тем же именем? - PullRequest
2 голосов
/ 06 января 2012

У меня есть класс с этой подписью (PHP 5.3):

class a {

    public static function __callStatic($name) {
        echo "unknown static method $name called";
    }

    public function foo() {
        echo "instance method foo called";
    }

}

Это делает это:

a::not_known();
// unknown static method not_known called -- CORRECT

$obj = new a();
$obj->foo();
// instance method foo called -- CORRECT

a::foo();
// instance method foo called -- WRONG
// should be: unknown static method foo called

Есть ли способ предотвратить вызов метода экземпляра, но использовать __callStatic для неизвестных статических методов? Если я вызываю статический метод, я хочу запустить статический метод ...


Редактировать : Почему не работает приведенный ниже ответ от SergeS (php 5.3.2):

class a {
    public $name = "a";

    function ident() {
        if( !is_object( $this )) { 
            echo "I am STATIC class a\n";
        } else {
            echo "I am INSTANCE class a\n";
            echo "\$this has name: $this->name\n";
        }
    }
}

class b {
    public $name = "b";

    function test() {
        a::ident();
    }
}

a::ident();
$a = new a();
$a->ident();

$b = new b();
$b->test();

дает следующий вывод:

a::ident();  --> I am STATIC class a // correct
$a->ident(); --> I am INSTANCE class a // correct
                 $this has name: a // correct
$b->test();  --> I am INSTANCE class a // wrong! should be 'STATIC class a'
                 $this has name: b // wrong! $this is an instance of 'b'!

В последнем вызове метод ident класса a вызывается статически в экземпляре b. И это передает экземпляр b как $this методу a, что, очевидно, совершенно неправильно!

1 Ответ

2 голосов
/ 06 января 2012

Это происходит во время определения __callStatic - он будет вызван, если метод с этим именем недоступен, но a :: foo есть (независимо от того, является он или не является статическим) - так что, если вы хотите сохранить этоКонструкция, поместите это в начало метода foo:

if( is_object( $this )) if( $this instanceof a ) { 
    // Do non-static
    return;
} 
// Do static here

PS Измените пример, чтобы убедиться, что он тоже будет таким же экземпляром - но это не всегда корректно в качестве ответа для статического или нестатического вызова select, потому что еслиу меня есть эта иерархия

Класс A -> Класс B -> Класс C (класс C реализует как A, так и B), если я хочу вызвать конкретный метод из A, я напишу A :: method (аналогично конкретномуметод в B, вызывая B :: method OR parent :: method)

...