兩大應用脈絡
| 層級 | 關鍵字位置 | 生命週期 | 可見範圍 |
| 函數內區域變數 | function foo() { static $x = 0; } | 腳本執行期間**永久存活** | 僅該函數內部 |
| 類別靜態成員 | class A { static $x; static function f() {} } | 類別被載入到腳本結束 | 全域 (透過 A::$x、self::$x、parent::$x) |
函數靜態變數:記住上一次的值
function counter() {
static $count = 0; // 只在第一次呼叫初始化
$count++;
echo "$count
";
}
counter(); // 1
counter(); // 2
counter(); // 3
應用場景:遞迴計數、快取昂貴計算結果、單次初始化資源 (如資料庫連線)。
類別靜態屬性與方法
class Config {
public static string $appName = 'MyApp';
protected static array $cache = [];
public static function get(string $key, $default = null) {
return self::$cache[$key] ?? $default;
}
public static function set(string $key, $value): void {
self::$cache[$key] = $value;
}
}
// 存取方式
echo Config::$appName; // 類別名稱::
Config::set('debug', true);
$debug = Config::get('debug');
關鍵字對比:self vs static vs $this
| 關鍵字 | 綁定時機 | 指向 | 可用於 |
self:: | **編譯期** (早期綁定) | **定義該類別**的類別 | 靜態屬性、靜態方法、常數 |
static:: | **執行期** (晚期靜態綁定 LSB) | **實際被呼叫**的類別 (子類別) | 靜態屬性、靜態方法 |
$this-> | 執行期 | 當前**實例物件** | 實例屬性、實例方法 |
parent:: | 編譯期 | 直接**父類別** | 覆寫時呼叫父實作 |
LSB 實戰:可被子類別覆寫的靜態工廠
class Model {
protected static string $table = 'models';
public static function create(array $data): self {
// 這裡用 static:: 而非 self::
return new static($data); // 實際 new 的是子類別
}
}
class User extends Model {
protected static string $table = 'users';
}
$user = User::create(['name' => 'John']); // 回傳 User 實例
靜態建構子模式 (PHP 無原生支援)
class Service {
public static string $config;
public static function init(): void {
// 複雜初始化邏輯:讀檔、連線、驗證
self::$config = json_decode(file_get_contents(__DIR__.'/config.json'), true);
}
}
// 類別定義後立即呼叫 (或在啟動腳本)
Service::init();
繼承體系下的靜態成員存取規則
class A {
public static $x = 'A';
public static function who() { echo self::$x; } // 早期綁定 → A
public static function whoLate() { echo static::$x; } // 晚期綁定 → 看誰呼叫
}
class B extends A {
public static $x = 'B';
}
A::who(); // A
B::who(); // A (self 綁定在 A)
A::whoLate(); // A
B::whoLate(); // B (static 解析為 B)
PHP vs C# static 差異速查
| 特性 | PHP | C# |
| 函數內 static 區域變數 | 支援 | 不支援 (需用類別靜態欄位) |
| 靜態類別 | 無 (用 final class + private constructor 模擬) | static class 關鍵字 |
| 靜態建構子 | 無 (手動 init()) | static Constructor() |
| 晚期靜態綁定 | static:: (PHP 5.3+) | 無 (需泛型/反射模擬) |
| 覆寫靜態方法 | 允許 (隱藏父方法) | 不允許 (new 隱藏而非覆寫) |
| 存取語法 | Class::$prop / Class::method() | Class.Prop / Class.Method() |
常見陷阱
- 靜態屬性共享陷阱:父子類別若未各自宣告
static $x,會共享同一記憶體位址
- Trait 靜態成員:每個使用 Trait 的類別都有**獨立副本**
- 序列化:
serialize() **不包含**靜態屬性
- 單元測試:靜態狀態導致測試相互干擾,需
tearDown 重置或用依賴注入替代