Ответ 1
Попробуйте следующее:
class Foo {
function bar() {
$static = !(isset($this) && get_class($this) == __CLASS__);
}
}
Источник: seancoates.com через Google
Можно ли каким-либо образом проверить, вызван ли метод статически или на экземпляр объекта?
Попробуйте следующее:
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'] == '::';
}
}
Проверка установки $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 переключается между классом child в контексте объекта и вызовом (?) класса в статическом контексте, замечательная магическая константа __class__
, оставалась как класс parent!
Вскоре после этого, после нахождения функции 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();