PHP 5 引入 const 關鍵字於類別內部定義常數,不同於全域 define(),類別常數具備命名空間隔離、可見度控制與自動載入優勢。本文詳細說明定義語法、存取方式與常見陷阱。
<?php
class Math {
// 類別常數定義:不需 $ 符號,慣例全大寫底線分隔
public const PI = 3.14159265359;
public const EULER = 2.71828182846;
private const INTERNAL_FACTOR = 1.5;
public function calculateCircleArea(float $radius): float {
// 類別內部存取:self::常數名
return self::PI * $radius ** 2;
}
public static function getConstants(): array {
return [
'PI' => self::PI,
'EULER' => self::EULER,
];
}
}
// 類別外部存取:類別名::常數名
echo Math::PI; // 3.14159265359
echo Math::EULER; // 2.71828182846
// echo Math::INTERNAL_FACTOR; // Fatal Error: private 常數不可外部存取
| 特性 | 說明 |
|---|---|
| 定義語法 | const 常數名 = 值; 不需 $ 符號 |
| 命名慣例 | 全大寫,單字底線分隔(如 MAX_CONNECTIONS) |
| 可見度 | 支援 public/protected/private(PHP 7.1+) |
| 值類型 | 純量(int, float, string, bool)、陣列(PHP 5.6+)、運算式(PHP 8.1+) |
| 存取方式 | self::常數(內部)、類別名::常數(外部)、static::常數(晚期靜態綁定) |
| 不可變性 | 定義後不可修改,嘗試修改拋出錯誤 |
| 繼承行為 | 子類別可定義同名常數覆蓋,父類別使用 self:: 仍指向父類別常數 |
<?php
class Config {
// 錯誤 1:嘗試在方法中修改常數
public const VERSION = '1.0';
public function setVersion(string $v) {
// self::VERSION = $v; // Fatal Error: Cannot modify const
}
// 錯誤 2:使用變數語法存取
// echo $this->VERSION; // Error: Access to undeclared static property
// 正確:唯讀屬性替代可變「常數」(PHP 8.1+)
public readonly string $version = '1.0';
// 正確:運算式定義常數(PHP 8.1+)
public const CACHE_TTL = 60 * 60 * 24; // 86400
public const DS = DIRECTORY_SEPARATOR;
}
class HttpStatus { const OK = 200; const NOT_FOUND = 404; }class Pagination { const DEFAULT_PER_PAGE = 20; }class UserType { const ADMIN = 'admin'; const USER = 'user'; }class Permission { const READ = 1; const WRITE = 2; const EXECUTE = 4; }<?php
class Base {
public const NAME = 'Base';
public static function whoAmI() {
echo static::NAME; // LSB:執行時解析為實際呼叫類別
}
}
class Child extends Base {
public const NAME = 'Child';
}
Base::whoAmI(); // 輸出: Base
Child::whoAmI(); // 輸出: Child(若用 self::NAME 則輸出 Base)
類別常數是表達「不變的類別層級資料」的標準方式。善用可見度控制、命名規範與 LSB 特性,能撰寫更清晰、安全且可維護的程式碼。PHP 8.1+ 的 readonly 屬性與 const 運算式支援,進一步擴展了適用場景。