static 在 PHP 中有三種截然不同的用法:函數內區域靜態變數、類別靜態屬性/方法、以及全域靜態變數(實為全域變數本質)。本文詳細解析前兩者的行為差異、初始化規則與實戰應用。
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:: 存取<?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
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 規範) | 低 (污染全域命名空間) |
private static int $count = 0;static:: 而非 self:: 確保呼叫子類覆寫的屬性/方法