首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP static 關鍵字深度解析:靜態屬性、靜態方法、晚期靜態綁定、單例模式

     編輯:PHP 綜合知識

核心概念

static 關鍵字用於聲明 **類層級** 的屬性與方法,屬於類本身而非實例。關鍵特性:

  • 無需實例化即可訪問:`ClassName::$prop`、`ClassName::method()`。
  • 所有實例共享同一份靜態屬性(單一內存地址)。
  • 靜態方法內 $this **不可用**(無物件上下文)。
  • 靜態屬性初始化只能用字面量/常量,不能用表達式(PHP 8.1+ 支援 `new Class()`)。

靜態屬性

class Config {
    // 僅允許字面量/常量
    public static string $appName = 'MyApp';
    public static int $maxRetry = 3;
    public static array $defaultHeaders = ['Content-Type' => 'application/json'];
    // public static $db = new PDO(...); // 錯誤:表達式不允許
}

// 訪問
echo Config::$appName; // MyApp
Config::$maxRetry = 5; // 修改影響所有後續訪問

// 繼承時的行為
class ChildConfig extends Config {
    public static string $appName = 'ChildApp'; // 遮蔽父類屬性
}
echo Config::$appName;   // MyApp
echo ChildConfig::$appName; // ChildApp

靜態方法

class MathUtil {
    public static function add(float $a, float $b): float {
        return $a + $b;
    }

    public static function factorial(int $n): int {
        return $n <= 1 ? 1 : $n * self::factorial($n - 1);
    }
}

// 調用
echo MathUtil::add(1, 2); // 3
echo MathUtil::factorial(5); // 120

// 動態調用(PHP 5.3+)
$class = 'MathUtil';
$method = 'add';
echo $class::$method(3, 4); // 7

晚期靜態綁定(LSB)

解決繼承中 `self::` 綁定到定義類而非調用類的問題。

class Model {
    protected static string $table = 'base_table';

    public static function getTable(): string {
        return static::$table; // LSB:綁定到調用類
    }

    public static function create(): self {
        return new static(); // 實例化調用類
    }
}

class User extends Model {
    protected static string $table = 'users';
}

echo User::getTable(); // 'users' (非 'base_table')
$user = User::create(); // 返回 User 實例

單例模式標準實現

class Database {
    private static ?self $instance = null;
    private PDO $pdo;

    private function __construct() {
        $this->pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    }

    // 禁止克隆與反序列化
    private function __clone() {}
    public function __wakeup() {
        throw new Exception("Cannot unserialize singleton");
    }

    public static function getInstance(): self {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function query(string $sql): PDOStatement {
        return $this->pdo->query($sql);
    }
}

// 使用
$db = Database::getInstance();
$stmt = $db->query('SELECT 1');

靜態與非靜態的訪問規則

調用方式靜態方法非靜態方法
Class::method()✅ 推薦⚠️ E_DEPRECATED (PHP 8.1+)
$obj->method()✅ 允許✅ 標準
self::method()✅ 編譯期綁定❌ 錯誤
static::method()✅ LSB❌ 錯誤
$this->method()❌ 無 $this✅ 標準

常見陷阱與最佳實踐

1. 靜態屬性在繼承中的共享/隔離

class Base {
    public static $counter = 0;
    public static function inc() { return ++self::$counter; }
}

class A extends Base {}
class B extends Base {}

A::inc(); // 1
B::inc(); // 2  ← 共享同一份 Base::$counter
A::inc(); // 3

// 若需隔離,子類必須重新聲明
class A2 extends Base { public static $counter = 0; }
class B2 extends Base { public static $counter = 0; }

2. 靜態變數在函數中(非類成員)

function counter() {
    static $count = 0; // 僅初始化一次
    return ++$count;
}
echo counter(); // 1
echo counter(); // 2
// 生命週期贯穿腳本執行,類似全局變數但作用域限制在函數內

3. 什麼時候用 static?

  • 工具類/助手類:無狀態、純函數邏輯(如 `Str::slug()`、`Arr::flatten()`)。
  • 單例/資源池:資料庫連接、配置管理、日誌器。
  • 緩存/註冊表:類級別快取、服務容器綁定。
  • 計數器/狀態追蹤:實例計數、遞歸深度、鎖標記。

4. 什麼時候**不**用 static?

  • 業務邏輯需依賴實例狀態(如用戶訂單、購物車)。
  • 需要多態行為(介面/抽象方法實現)。
  • 單元測試困難(靜態難以 Mock,改用依賴注入)。

PHP 8.1+ 新特性

class Modern {
    // 初始化表達式支援
    public static PDO $pdo = new PDO('sqlite::memory:');
    
    // readonly 靜態屬性(PHP 8.1+)
    public static readonly string $version = '1.0.0';
    
    // 靜態返回類型聲明
    public static function create(): static {
        return new static();
    }
}

總結

static 是 PHP 面向對象的核心機制之一,正確理解「類層級共享」、「無 `$this` 上下文」、「`self` vs `static` 綁定差異」是寫出健壯代碼的關鍵。善用靜態方法構建無狀態工具類,謹慎使用靜態屬性存儲全局狀態,避免隱式耦合導致測試與維護困難。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved