Как мне проверить в PHP, что я нахожусь в статическом контексте (или нет)? - PullRequest
29 голосов
/ 07 декабря 2009

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

Ответы [ 10 ]

56 голосов
/ 07 декабря 2009

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

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

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

11 голосов
/ 07 июля 2010

«Выкопать его из 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'] == '::';
    }
}

8 голосов
/ 07 декабря 2009

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

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

6 голосов
/ 07 декабря 2012

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

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 исправит это и позволит избежать конфликтов с классами, которые могут реализовывать ваши «полустатические» функции.

3 голосов
/ 07 декабря 2009

Тест для $this:

class Foo {

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

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

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

Edit: Как указывает pygorex1, вы также можете force метод, который будет оцениваться статически:

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"
2 голосов
/ 02 сентября 2012

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

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__ магическая константа осталась родительской для класса!

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

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

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

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

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

1 голос
/ 31 января 2017

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

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

__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 в статическом контексте

1 голос
/ 07 декабря 2009
<?

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

}

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

Редактировать: избили его.

1 голос
/ 07 декабря 2009

Проверьте, определено ли $this

0 голосов
/ 22 декабря 2016

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

return new self();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...