Làm cách nào để lấy tên lớp từ một lệnh gọi tĩnh trong một lớp PHP mở rộng?


93

Tôi có hai lớp: ActionMyAction. Cái sau được khai báo là:

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

Tất cả những gì tôi cần là phương thức trong Actionlớp (chỉ trong đó, vì sẽ có rất nhiều lớp kế thừa và tôi không muốn triển khai phương thức này trong tất cả chúng), phương thức này sẽ trả về tên lớp từ một cuộc gọi tĩnh. Đây là những gì tôi đang nói về:

Class Action {
 function n(){/* something */}
}

Và khi tôi gọi nó:

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

Nhưng mỗi khai báo trong lớp cha chỉ có quyền truy cập vào __CLASS__biến lớp cha , có giá trị “Hành động”.

Có cách nào có thể để làm điều này?

Câu trả lời:


176

__CLASS__luôn trả về tên của lớp mà nó đã được sử dụng, vì vậy nó không giúp ích nhiều cho phương thức tĩnh. Nếu phương thức không tĩnh, bạn chỉ cần sử dụng get_class ($ this). ví dụ

class Action {
    public function n(){
        echo get_class($this);
    }

}

class MyAction extends Action {

}

$foo=new MyAction;

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

Các liên kết tĩnh muộn, có sẵn trong PHP 5.3+

Bây giờ PHP 5.3 đã được phát hành, bạn có thể sử dụng các liên kết tĩnh trễ , cho phép bạn giải quyết lớp đích cho một cuộc gọi phương thức tĩnh trong thời gian chạy thay vì khi nó được định nghĩa.

Mặc dù tính năng này không giới thiệu một hằng số ma thuật mới để cho bạn biết tên lớp mà bạn đã được gọi, nhưng nó cung cấp một hàm mới, get_called_class () có thể cho bạn biết tên của lớp mà một phương thức tĩnh đã được gọi. Đây là một ví dụ:

Class Action {
    public static function n() {
        return get_called_class();
    }
}


class MyAction extends Action {

}


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

Vấn đề duy nhất đối với OP là tính năng này vẫn chưa khả dụng. PHP 5.3 vẫn chưa được thử nghiệm.
Ionuț G. Stan

3
@Paul, cảm ơn! Bạn chỉ cần lưu ngày của tôi ... hay đêm với get_called_class():)
Marecky

1
Tôi ước ai đó có thể giúp tôi với một vấn đề tương tự . Tập lệnh PHP chết lặng lẽ khi thực thi new static();từ bên trong một phương thức tĩnh riêng tư (sử dụng xampp trên windows và php> 5.5). :s
Stphane

$ foo = new MyAction; echo get_class ($ foo); Điều này cũng in MyAction.
sammry

41

Vì 5.5, bạn có thể sử dụng classtừ khóa để phân giải tên lớp , điều này sẽ nhanh hơn rất nhiều so với việc thực hiện các cuộc gọi hàm. Cũng hoạt động với các giao diện.

// 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

16

Nó không phải là giải pháp lý tưởng, nhưng nó hoạt động trên PHP <5.3.0.

Mã đã được sao chép từ septuro.com

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();
    }
}


2
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();

0

Không có cách nào, trong các phiên bản PHP có sẵn, để làm những gì bạn muốn. Giải pháp của Paul Dixon là duy nhất. Ý tôi là, ví dụ về mã, vì tính năng liên kết tĩnh muộn mà anh ấy đang nói đến có sẵn kể từ PHP 5.3, đang trong giai đoạn thử nghiệm.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.