Есть ли способ проверить, вызван ли метод статически или на экземпляр объекта?
Попробуйте следующее:
class Foo { function bar() { $static = !(isset($this) && get_class($this) == __CLASS__); } }
Источник: seancoates.com через Google
«Выкапывать его из 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'] == '::'; } }
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'] == '::'; } }
Проверка того, установлен ли $this
, не будет работать всегда.
Если вы вызываете статический метод из объекта, то $this
будет задан как контекст вызывающих. Если вам действительно нужна информация, я думаю, вам придется выкапывать ее из debug_backtrace
. Но зачем вам это нужно в первую очередь? Скорее всего, вы можете изменить структуру своего кода таким образом, чтобы вы этого не сделали.
Я действительно использую эту строку кода во всех моих сценариях, она работает хорошо и предотвращает ошибки.
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
исправит это и позволит избежать конфликта с классами, которые могут реализовать ваши «полустатические» функции.
Тест для $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"
Тестирование 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 переключается между тем, что он является дочерним по классу в контексте объекта и вызовом (?) класса в статическом контексте, замечательная магическая константа __class__
осталась в качестве родительского класса!
Вскоре после этого, после нахождения функции is_a, мы можем теперь проверить, находимся ли мы в статическом контексте:
if( is_a($this, __CLASS__) ) ...
Возвращает true в контексте объекта, false в статическом контексте.
Проверьте свои собственные реализации, поскольку я тестирую это только для своего конкретного сценария (уникальный случай вызова наследования) в 5.3.
К сожалению (для моего случая) я еще не смог найти способ вызвать static_bar()
поскольку $ this и static ссылаются на отдельный класс, а __class__
ссылается на родительский класс. Мне нужен способ вызова child :: static_bar () …
Проверьте, определено ли $this
<? class A { function test() { echo isset($this)?'not static':'static'; } } $a = new A(); $a->test(); A::test(); ?>
Изменить: избили.
Это старый вопрос, но я добавлю альтернативный ответ.
Существует два магических метода
__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» в статическом контексте
Просто верните класс как новый в функцию.
return new self();