Как проверить на PHP, что я в статическом контексте (или нет)?

Можно ли каким-либо образом проверить, вызван ли метод статически или на экземпляр объекта?

Ответы

Ответ 1

Попробуйте следующее:

class Foo {
   function bar() {
      $static = !(isset($this) && get_class($this) == __CLASS__);
   }
}

Источник: seancoates.com через Google

Ответ 2

"Выкапывать его из debug_backtrace()" не слишком много. У debug_backtrace() был член 'type', который является '::', если вызов статический, а '- > ', если это не так. Итак:

class MyClass {
    public function doStuff() {
        if (self::_isStatic()) {
            // Do it in static context
        } else {
            // Do it in object context
        }
    }

    // This method needs to be declared static because it may be called
    // in static context.
    private static function _isStatic() {
        $backtrace = debug_backtrace();

        // The 0th call is to _isStatic(), so we need to check the next
        // call down the stack.
        return $backtrace[1]['type'] == '::';
    }
}

Ответ 3

Проверка установки $this не будет работать всегда.

Если вы вызываете статический метод из объекта, то $this будет установлен как контекст вызывающих. Если вам действительно нужна информация, я думаю, вам придется выкапывать ее из debug_backtrace. Но зачем вам это нужно в первую очередь? Скорее всего, вы можете изменить структуру своего кода таким образом, чтобы вы этого не сделали.

Ответ 4

Я действительно использую эту строку кода для всех моих скриптов, она работает хорошо и предотвращает ошибки.

class B{
      private $a=1;
      private static $static=2;

      function semi_static_function(){//remember,don't declare it static
        if(isset($this) && $this instanceof B)
               return $this->a;
        else 
             return self::$static;
      }
}

Использование instanceof не является паранойей:

Если класс A вызывает класс B, статическая функция $this может существовать в области A; Я знаю, что это довольно перепутано, но php делает это.

instanceof исправит это и позволит избежать конфликтов с классами, которые могут реализовать ваши "полустатические" функции.

Ответ 5

Тест для $this:

class Foo {

    function bar() {
        if (isset($this)) {
            echo "Y";
        } else {
            echo "N";
        }
    }
}

$f = new Foo();
$f->bar(); // prints "Y"

Foo::bar(); // prints "N"

Изменить: Как указывает pygorex1, вы также можете заставить метод оцениваться статически:

class Foo {

    static function bar() {
        if (isset($this)) {
            echo "Y";
        } else {
            echo "N";
        }
    }
}

$f = new Foo();
$f->bar(); // prints "N", not "Y"!

Foo::bar(); // prints "N"

Ответ 6

Тестирование isset ($ this) для меня не работало, как упоминалось в troelskn "$, это будет установлено как контекст вызывающих."

abstract class parent
{
    function bar()
    {
        if( isset( $this ) ) do_something();
        else static::static_bar();
    }

    function static static_bar()
    {
        do_something_in_static_context();
    }
}

class child extends parent
{
    ...
}

$foo = new child();
$foo->bar(); //results in do_something()
child::bar(); //also results in do_something()

В моем случае у меня есть родительский класс с объектной и статической функцией контекста, которая выполняет одну и ту же задачу в дочернем классе. isset ($ this) всегда возвращался true, однако я заметил, что в то время как $this переключается между классом child в контексте объекта и вызовом (?) класса в статическом контексте, замечательная магическая константа __class__, оставалась как класс parent!

Вскоре после этого, после нахождения функции is_a, мы можем теперь проверить, находимся ли мы в статическом контексте:

if(  is_a($this, __CLASS__) ) ...

Возвращает true в контексте объекта, false в статическом контексте.

Протестируйте свои собственные реализации, поскольку я тестирую только это для своего конкретного сценария (уникальный случай вызова наследования) в 5.3.

К сожалению (для моего случая) я еще не смог найти способ вызвать static_bar(), поскольку $this и static ссылаются на отдельный класс, а __class__ ссылается на родительский класс. Мне нужен способ вызова child:: static_bar()...

Ответ 7

Проверить, установлен ли $this

Ответ 8

<?

class A {
    function test() {
            echo isset($this)?'not static':'static';                                }

}

$a = new A();
$a->test();
A::test();
?>

Изменить: избили его.

Ответ 9

Это старый вопрос, но я добавлю альтернативный ответ.

Есть два магических метода

__call($name, $arguments)
запускается при вызове недоступных методов в контексте объекта.

__callStatic($name, $arguments)
запускается при вызове недоступных методов в статическом контексте.

<?php
class MethodTest
{
    public function __call($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling object method '$name' "
             . implode(', ', $arguments). "\n";
    }

    /**  As of PHP 5.3.0  */
    public static function __callStatic($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling static method '$name' "
             . implode(', ', $arguments). "\n";
    }
}

$obj = new MethodTest;
$obj->runTest('in object context');

MethodTest::runTest('in static context');  // As of PHP 5.3.0

Выходы

Вызов метода объекта "runTest" в объектном контексте
Вызов статического метода "runTest" в статическом контексте

Ответ 10

Просто верните класс как новый в функции.

return new self();