关于oop:如何从扩展PHP类中的静态调用中获取类名?

How can I get the classname from a static call in an extended PHP class?

我有两个班:ActionMyAction。后者声明为:

1
class MyAction extends Action {/* some methods here */}

我只需要Action类中的方法(只在其中,因为会有很多继承的类,我不想在所有这些类中实现这个方法),它将从静态调用中返回类名。以下是我要说的:

1
2
3
Class Action {
 function n(){/* something */}
}

当我称之为:

1
MyAction::n(); // it should return"MyAction"

但是父类中的每个声明都只能访问父类__CLASS__变量,该变量的值为"action"。

有什么可行的方法吗?


__CLASS__总是返回使用它的类的名称,因此对于静态方法来说,它没有多大帮助。如果方法不是静态的,您可以简单地使用get_类($this)。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Action {
    public function n(){
        echo get_class($this);
    }

}

class MyAction extends Action {

}

$foo=new MyAction;

$foo->n(); //displays 'MyAction'

最新的静态绑定,在php 5.3中可用+

既然已经发布了php 5.3,那么可以使用后期的静态绑定,这样可以在运行时而不是在定义静态方法时解析静态方法调用的目标类。

虽然这个特性没有引入一个新的魔力常数来告诉你被调用的类名,但是它提供了一个新的函数get _called _class(),它可以告诉你一个静态方法被调用的类的名称。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
Class Action {
    public static function n() {
        return get_called_class();
    }
}


class MyAction extends Action {

}


echo MyAction::n(); //displays MyAction


由于5.5,您可以使用class关键字进行类名解析,这比进行函数调用快得多。也适用于接口。

1
2
3
4
5
6
// C extends B extends A

static::class  // MyNamespace\ClassC when run in A
self::class    // MyNamespace\ClassA when run in A
parent::class  // MyNamespace\ClassB when run in C
MyClass::class // MyNamespace\MyClass


这不是理想的解决方案,但它适用于php<5.3.0。

代码是从septuro.com复制的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
if(!function_exists('get_called_class')) {
    class class_tools {
        static $i = 0;
        static $fl = null;

        static function get_called_class() {
            $bt = debug_backtrace();

            if (self::$fl == $bt[2]['file'].$bt[2]['line']) {
                self::$i++;
            } else {
                self::$i = 0;
                self::$fl = $bt[2]['file'].$bt[2]['line'];
            }

            $lines = file($bt[2]['file']);

            preg_match_all('/([a-zA-Z0-9\_]+)::'.$bt[2]['function'].'/',
                $lines[$bt[2]['line']-1],
                $matches);

            return $matches[1][self::$i];
        }
    }

    function get_called_class() {
        return class_tools::get_called_class();
    }
}


现在(当5.3到达时)很简单:

http://php.net/manual/en/function.get-called-class.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class MainSingleton {
  private static $instances = array();
  private static function get_called_class() {
    $t = debug_backtrace();
    return $t[count($t)-1]["class"];
  }  

  public static function getInstance() {
    $class = self::get_called_class();
    if(!isset(self::$instances[$class]) ) {
      self::$instances[$class] = new $class;
    }
    return self::$instances[$class];
  }

}

class Singleton extends MainSingleton {
  public static function getInstance()
  {
    return parent::getInstance();
  }    
  protected function __construct() {
    echo"A". PHP_EOL;
  }

  protected function __clone() {}

  public function test() {
    echo" * test called *";
  }
}

Singleton::getInstance()->test();
Singleton::getInstance()->test();

在可用的PHP版本中,无法执行您想要的操作。保罗·狄克逊的解决方案是唯一的。我的意思是,这个代码示例,作为他所说的最新的静态绑定特性,可以从PHP5.3开始使用,后者是beta版本。