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

PHP 靜態變量深度解析:生命週期、作用域、晚靜態綁定與實戰模式

     編輯:PHP 綜合知識

核心概念

  • 函數內靜態變量:函數調用間保持值,生命週期 = 腳本執行期間,作用域 = 函數內部。
  • 類靜態屬性:屬於類而非實例,所有實例共享,支援繼承、晚靜態綁定 (LSB)。
  • 類靜態方法:無需實例化調用,$this 不可用,支援 LSB。

函數靜態變量

<?php
function counter() {
    static $count = 0; // 僅初始化一次
    $count++;
    echo "調用第 $count 次\n";
}

counter(); // 1
counter(); // 2
counter(); // 3

// 遞歸計數
function traverse($node, &$depth = 0) {
    static $maxDepth = 0;
    $depth++;
    $maxDepth = max($maxDepth, $depth);
    // ... 遍歷子節點
    $depth--;
    return $maxDepth;
}

// 緩存昂貴計算結果
function expensiveConfig() {
    static $cache = null;
    if ($cache === null) {
        // 模擬讀取配置文件、解析 YAML
        $cache = ['debug' => true, 'db' => '...'];
    }
    return $cache;
}

類靜態屬性與方法

<?php
class Child {
    public static int $count = 0; // 靜態屬性(PHP 7.4+ 類型聲明)
    public string $name;

    public function __construct(string $name) {
        $this->name = $name;
        self::$count++; // 類內訪問:self:: 或 static::
    }

    public function joinGame(): void {
        echo "{$this->name} 加入遊戲,當前 " . self::$count . " 人\n";
    }

    // 靜態方法
    public static function getCount(): int {
        return self::$count;
    }

    // 晚靜態綁定 (LSB) 示例
    public static function whoAmI(): string {
        return static::class; // 運行時解析為調用類
    }
}

class BraveChild extends Child {
    public static int $count = 0; // 子類獨立計數
}

$c1 = new Child('李逵');
$c1->joinGame(); // 1
$c2 = new Child('張飛');
$c2->joinGame(); // 2
$b1 = new BraveChild('孫悟空');
$b1->joinGame(); // 1 (獨立計數)

echo Child::getCount();      // 2
echo BraveChild::getCount(); // 1
echo Child::whoAmI();        // Child
echo BraveChild::whoAmI();   // BraveChild

晚靜態綁定 (Late Static Binding) 核心

關鍵字解析時機指向
self::編譯期定義該代碼的類
static::運行期實際調用的類
parent::編譯期父類
static::class運行期調用類全限定名
<?php
class Base {
    public static function factory(): self {
        return new static(); // LSB:返回調用類的實例
    }
    public static function getName(): string {
        return self::class; // 總是 Base
    }
    public static function getCalled(): string {
        return static::class; // 調用者類名
    }
}

class User extends Base {}
class Admin extends Base {}

$user = User::factory();   // User 實例
$admin = Admin::factory(); // Admin 實例

echo User::getName();   // Base
echo User::getCalled(); // User
echo Admin::getCalled(); // Admin

實戰設計模式

1. 單例模式

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

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

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

    public function getPdo(): PDO {
        return $this->pdo;
    }
    // 禁止克隆、序列化
    private function __clone() {}
    public function __wakeup() { throw new \Exception("Cannot unserialize singleton"); }
}

2. 註冊表/服務容器

<?php
class Container {
    private static array $services = [];

    public static function bind(string $key, callable $factory): void {
        self::$services[$key] = $factory;
    }

    public static function make(string $key) {
        if (!isset(self::$services[$key])) {
            throw new \Exception("Service $key not found");
        }
        return self::$services[$key]();
    }
}

// 使用
Container::bind('db', fn() => new PDO(...));
$db = Container::make('db');

3. 靜態緩存模式

<?php
class Config {
    private static array $cache = [];

    public static function get(string $key, $default = null) {
        if (!isset(self::$cache[$key])) {
            self::$cache[$key] = self::loadFromFile($key) ?? $default;
        }
        return self::$cache[$key];
    }

    private static function loadFromFile(string $key) {
        // 讀取 config/{$key}.php 返回陣列
    }
}

常見誤區與避坑

誤區正確理解
靜態屬性 = 全局變量受類作用域限制,`Class::$prop` 訪問,支持 `private/protected` 封裝
繼承共享父類靜態屬性子類**不**自動共享,除非子類未重新聲明(PHP 8.1+ 提示 Deprecated)
靜態方法可用 $this不可用,靜態上下文無實例
靜態變量線程安全PHP 單線程請求模型下安全,Swoole/Workerman 多進程需額外同步
靜態屬性可序列化`serialize()` 不包含靜態屬性,需手動實現 `__sleep/__wakeup`

總結

靜態變量是**類級/函數級狀態**的核心工具。善用 static:: (LSB) 實現多態工廠、單例、容器;函數靜態變量用於緩存、計數、遞歸輔助。**嚴禁濫用作為全局狀態容器**,導致耦合、難測試、併發隱患。

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