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

PHP static 靜態變數完整解析:區域靜態 vs 全域靜態、初始化規則與應用場景

     編輯:PHP 綜合知識

PHP static 關鍵字深度解析:區域靜態變數與全域靜態變數

static 在 PHP 中有三種截然不同的用法:函數內區域靜態變數、類別靜態屬性/方法、以及全域靜態變數(實為全域變數本質)。本文詳細解析前兩者的行為差異、初始化規則與實戰應用。

一、函數內區域靜態變數

核心特性

  1. 生命週期贯穿整個腳本執行:不會隨函數呼叫結束而銷毀
  2. 作用域僅限定義它的函數內部:外部無法直接存取
  3. 只初始化一次:首次呼叫函數時初始化,後續呼叫保留上次值
  4. 初始值限制:只能是常量值或常量表達式 (PHP 5.6+ 支援 1+1),不能使用變數、函數回傳值

代碼範例

<?php
function counter() {
    static $count = 0; // 只初始化一次
    $count++;
    echo "呼叫次數: $count\n";
}

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

// 錯誤示範
function badInit() {
    // static $val = someFunction(); // ❌ Fatal error (PHP 5.6 前)
    // static $val = $externalVar;    // ❌ Fatal error
    static $val = 1 + 1;             // ✅ PHP 5.6+ 常量表達式
    static $val = 'prefix_' . 'suffix'; // ✅ PHP 5.6+ 常量表達式
}

經典應用:遞歸計數、單例快取、避免重複初始化

<?php
// 1. 遞歸深度計數
function traverse($node, $depth = 0) {
    static $maxDepth = 0;
    if ($depth > $maxDepth) $maxDepth = $depth;
    // ... 遍歷子節點 ...
    return $maxDepth;
}

// 2. 惰性初始化昂貴資源
function getDbConnection() {
    static $pdo = null;
    if ($pdo === null) {
        $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    return $pdo;
}

// 3. 函數級快取
function expensiveCalculation($input) {
    static $cache = [];
    if (!isset($cache[$input])) {
        $cache[$input] = reallyExpensiveOperation($input);
    }
    return $cache[$input];
}

二、類別靜態屬性與方法

核心特性

  • 屬於類別本身,不屬於某個實例
  • 所有實例共享同一份靜態屬性
  • 可用 self::、static:: (晚期靜態綁定)、ClassName:: 存取
  • 靜態方法中 $this 不可用

代碼範例

<?php
class User {
    private static $instanceCount = 0;
    private static $instances = [];
    
    public $name;
    
    public function __construct($name) {
        $this->name = $name;
        self::$instanceCount++;
        self::$instances[] = $this;
    }
    
    public static function getInstanceCount() {
        return self::$instanceCount;
    }
    
    public static function getAllInstances() {
        return self::$instances;
    }
}

$user1 = new User('Alice');
$user2 = new User('Bob');
echo User::getInstanceCount(); // 2

三、全域變數 vs 區域靜態變數

PHP 中全域變數本質就是靜態儲存 (生命週期贯穿腳本),但作用域不同:

<?php
$globalVar = 0; // 全域變數

function testGlobal() {
    global $globalVar;
    $globalVar++;
    echo "Global: $globalVar\n";
}

function testStatic() {
    static $staticVar = 0;
    $staticVar++;
    echo "Static: $staticVar\n";
}

testGlobal(); // Global: 1
testGlobal(); // Global: 2
testStatic(); // Static: 1
testStatic(); // Static: 2

echo $globalVar; // 2 (可存取)
// echo $staticVar; // ❌ Notice: Undefined variable

對比總結表

特性區域靜態變數類別靜態屬性全域變數
宣告位置函數內部類別內部函數外部
作用域僅該函數類別/實例/外部 (視存取修飾子)全域 (需 global 宣告)
生命週期腳本執行期間腳本執行期間腳本執行期間
初始化首次呼叫函數時腳本載入類別時執行到宣告行時
共享範圍同一函數的所有呼叫所有實例與類別本身所有作用域 (含 include 檔案)
可用性高 (封裝性好)高 (OOP 規範)低 (污染全域命名空間)

最佳實踐建議

  1. 優先使用類別靜態屬性:OOP 封裝性佳、可控制存取權限、支援繼承與晚期靜態綁定
  2. 函數級快取/狀態用區域靜態:簡單、封裝、無需建立類別
  3. 避免使用全域變數:難以測試、命名衝突、隱性耦合
  4. 靜態屬性初始化:PHP 8.0+ 支援型別宣告 private static int $count = 0;
  5. 晚期靜態綁定 (LSB):繼承體系中用 static:: 而非 self:: 確保呼叫子類覆寫的屬性/方法
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved