static 是 PHP 面向對象核心關鍵字,用於聲明類級別的屬性與方法,以及實現晚期靜態綁定 (LSB)。本文系統講解語法規則、內存模型、常見陷阱、LSB 原理與實戰應用模式。
<?php
class Foo {
// 靜態屬性:屬於類,不屬於實例
public static $myStatic = 'foo';
// 靜態方法:可無實例調用,$this 不可用
public static function staticValue() {
return self::$myStatic; // self 指向當前類 (Foo)
}
// 非靜態方法
public function instanceMethod() {
return self::$myStatic; // 也可訪問靜態屬性
}
}
class Bar extends Foo {
public static function fooStatic() {
return parent::$myStatic; // 訪問父類靜態屬性
}
}
// 訪問方式
echo Foo::$myStatic; // 類名::屬性
echo Foo::staticValue(); // 類名::方法
$obj = new Foo();
echo $obj->staticValue(); // 實例也可調用靜態方法 (不推薦)
echo $obj::$myStatic; // PHP 5.3+ 實例訪問靜態屬性
$class = 'Foo';
echo $class::$myStatic; // 變量類名動態調用 (PHP 5.3+)
?>
| 特性 | 靜態成員 | 實例成員 |
|---|---|---|
| 所屬 | 類 | 對象實例 |
| 內存 | 進程生命周期內單一份 | 每個實例獨立一份 |
| 訪問方式 | Class::$prop Class::method() | $obj->prop $obj->method() |
| $this 可用性 | 不可用 | 可用 |
| 繼承行為 | 父子類共享同一內存 (除非子類重新聲明) | 每個實例獨立 |
| 初始化值 | 只能是字面量/常量/常量表達式 (PHP 5.6+) | 任意表達式 |
| 序列化 | 不隨對象序列化 | 序列化 |
<?php
class Test {
// 合法
public static $a = 1;
public static $b = 'str';
public static $c = [1,2,3];
public static $d = SOME_CONST;
public static $e = 1 + 2; // PHP 5.6+ 常量表達式
// 非法 (編譯錯誤)
// public static $f = someFunc(); // 函數調用
// public static $g = new StdClass(); // 對象實例化
// public static $h = $externalVar; // 變量
}
?>
問題:self:: 綁定到定義該方法的類 (編譯時綁定),導致繼承時無法調用子類覆寫的靜態成員。
<?php
class A {
public static function who() { echo __CLASS__; }
public static function testSelf() { self::who(); } // 編譯時綁定到 A
public static function testStatic() { static::who(); } // 運行時綁定到調用類
}
class B extends A {
public static function who() { echo __CLASS__; }
}
A::testSelf(); // 輸出 A
A::testStatic(); // 輸出 A
B::testSelf(); // 輸出 A (問題!)
B::testStatic(); // 輸出 B (正確!)
?>
<?php
abstract class Model {
protected static $table = '';
// 子類必須實現
abstract protected static function getTable();
public static function find($id) {
$table = static::getTable(); // LSB 獲取子類表名
$sql = "SELECT * FROM $table WHERE id = ?";
// ... 執行查詢返回 static::class 實例
return new static(); // PHP 5.4+ new static() 實例化調用類
}
}
class User extends Model {
protected static function getTable() { return 'users'; }
}
$user = User::find(1); // 正確操作 users 表並返回 User 實例
?>
<?php
function counter() {
static $count = 0; // 僅初始化一次,生命周期贯穿腳本
return ++$count;
}
echo counter(); // 1
echo counter(); // 2
echo counter(); // 3
// 應用場景:單例模式、緩存、避免重複初始化
function getConfig() {
static $config = null;
if ($config === null) {
$config = parse_ini_file('/path/config.ini');
}
return $config;
}
?>
Str::slug()、Arr::get()、Carbon::now()。static $instance、static::getInstance()。parent::$prop 訪問父類副本。public static readonly string $VERSION = '1.0'; 初始化後不可修改。self:: 調用可覆寫方法:改用 static:: 實現多態。