<?php
class A {
public function __construct() {
echo __CLASS__; // 輸出 'A'
}
public static function whoami() {
echo __CLASS__; // 輸出 'A'
}
}
class B extends A {}
new B(); // 輸出 A (預期 B)
B::whoami(); // 輸出 A (預期 B)
?>
原因:__CLASS__、__METHOD__、__FUNCTION__ 是**編譯期常數**,在定義該類別的檔案中解析,**不具備多態性**。
| 方法 | 適用場景 | PHP 版本 | 回傳值 | 效能 |
|---|---|---|---|---|
get_class($this) | 實例方法 | 所有版本 | 實際實例化的類別名稱 | 極快 (內建) |
get_called_class() | 靜態方法 (LSB - Late Static Binding) | PHP 5.3+ | 實際呼叫的類別名稱 | 極快 (內建) |
static::class | 靜態方法 (PHP 8+) | PHP 8.0+ | 實際呼叫的類別名稱 | 編譯期解析,最快 |
self::class | 靜態方法 | PHP 5.5+ | 定義該方法的類別名稱 (等同 __CLASS__) | 編譯期解析 |
<?php
class A {
public function __construct() {
echo get_class($this); // 輸出實際實例類別
}
public static function whoami() {
// PHP 5.3+
echo get_called_class();
// PHP 8.0+ 推薦
// echo static::class;
}
}
class B extends A {}
new B(); // 輸出 B
B::whoami(); // 輸出 B
?>
若被迫維護 PHP 5.2 專案 (已 EOL,極不建議),可用 debug_backtrace() 解析呼叫堆疊:
<?php
if (!function_exists('get_called_class')) {
function get_called_class(): string {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
// 尋找靜態呼叫框架
foreach ($trace as $frame) {
if (isset($frame['class'], $frame['type']) && $frame['type'] === '::') {
return $frame['class'];
}
}
// 回退:解析原始碼行 (效能極差,僅救急)
$frame = $trace[1] ?? [];
if (isset($frame['file'], $frame['line'])) {
$lines = file($frame['file']);
$line = $lines[$frame['line'] - 1] ?? '';
if (preg_match('/(\w+)::\w+/', $line, $m)) {
return $m[1];
}
}
return 'Unknown';
}
}
?>
警告:此方案**效能極差、依賴原始碼格式、無法在 eval/動態建構類別中運作**。**請升級 PHP ≥ 5.3**。
<?php
abstract class Model {
protected static $table = 'base_table';
public static function getTable(): string {
return static::$table; // LSB: 取得子類別的靜態屬性
}
public static function find(int $id): ?self {
$table = static::getTable();
// SELECT * FROM $table WHERE id = $id
return new static(); // LSB: 實例化子類別
}
}
class User extends Model {
protected static $table = 'users';
}
class Order extends Model {
protected static $table = 'orders';
}
echo User::getTable(); // users
echo Order::getTable(); // orders
$user = User::find(1); // 回傳 User 實例
$order = Order::find(1); // 回傳 Order 實例
?>
get_class($this)。get_called_class(),PHP 8+ 用 static::class。__CLASS__、self::class** 於需要多態的靜態情境。