PHP里的CLASS这类东西是静态绑定的,如果不在子类里重载的话,那么继承父类方法所得到的依旧是父类的名称,而不是子类的名称,比如:

  1. <?php
  2. class A
  3. {
  4. function __construct()
  5. {
  6. echo __CLASS__;
  7. }
  8. static function name()
  9. {
  10. echo __CLASS__;
  11. }
  12. }
  13. class B extends A
  14. {
  15. }
  16. $objB = new B(); // 输出 A
  17. B::name(); // 输出 A

此时,无论将B实例化还是直接调用静态方法,echo出来的都会是A。

而实际上我想要得到的是 子类B 的名称!那如何实现呢?

PHP自带两个函数 get_class() 和 get_called_class() 可以解决这个问题。

get_class() 用于实例调用,加入参数($this)可解决子类继承调用的问题,而 get_called_class() 则是用于静态方法调用。

需要注意的是: get_called_class() 需要 PHP>=5.3.0 才支持,官方手册: http://php.net/manual/en/function.get-called-class.php ,对于 PHP5.3.0以下的版本,有人给出了如下实现方式:

  1. <?php
  2. if (!function_exists('get_called_class'))
  3. {
  4. class classTools
  5. {
  6. private static $i = 0;
  7. private static $file = null;
  8. public static function get_called_class()
  9. {
  10. $bt = debug_backtrace();
  11. // 使用 call_user_func 或 call_user_func_array 函数调用类方法,处理如下
  12. if (array_key_exists(3, $bt) && array_key_exists('function', $bt[3]) && in_array($bt[3]['function'], array('call_user_func', 'call_user_func_array'))
  13. )
  14. {
  15. // 如果参数是数组
  16. if (is_array($bt[3]['args'][0]))
  17. {
  18. $toret = $bt[3]['args'][0][0];
  19. return $toret;
  20. }
  21. else if (is_string($bt[3]['args'][0]))
  22. {
  23. // 如果参数是字符串
  24. // 如果是字符串且字符串中包含::符号,则认为是正确的参数类型,计算并返回类名
  25. if (false !== strpos($bt[3]['args'][0], '::'))
  26. {
  27. $toret = explode('::', $bt[3]['args'][0]);
  28. return $toret[0];
  29. }
  30. }
  31. }
  32. // 使用正常途径调用类方法,如:A::make()
  33. if (self::$file == $bt[2]['file'] . $bt[2]['line'])
  34. {
  35. self::$i++;
  36. }
  37. else
  38. {
  39. self::$i = 0;
  40. self::$file = $bt[2]['file'] . $bt[2]['line'];
  41. }
  42. $lines = file($bt[2]['file']);
  43. preg_match_all('/([a-zA-Z0-9\_]+)::' . $bt[2]['function'] . '/', $lines[$bt[2]['line'] - 1], $matches);
  44. return $matches[1][self::$i];
  45. }
  46. }
  47. function get_called_class()
  48. {
  49. return classTools::get_called_class();
  50. }
  51. }

现在,把例子修改下:

  1. <?php
  2. class A
  3. {
  4. function __construct()
  5. {
  6. echo get_class($this);
  7. }
  8. static function name()
  9. {
  10. echo get_called_class();
  11. }
  12. }
  13. class B extends A
  14. {
  15. }
  16. $objB = new B(); // 输出 B
  17. B::name(); // 输出 B

呵呵,是我想要的结果!

Example #1 get_called_class() 的使用

  1. <?php
  2. class foo
  3. {
  4. public static function test()
  5. {
  6. var_dump(get_called_class());
  7. }
  8. }
  9. class bar extends foo
  10. {
  11. }
  12. foo::test();
  13. bar::test();

以上例程会输出:

string(3) “foo”
string(3) “bar”

  1. <?php
  2. class someClass
  3. {
  4. public static $container = '2';
  5. public function someMethod()
  6. {
  7. echo static::$container === self::$container;
  8. }
  9. }
  10. $anObject = new someClass();
  11. $anObject->someMethod(); //输出1,也就是true啦。

分类: web

标签:   php