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

PHP static 靜態關鍵字深度解析:變數、方法、延遲靜態綁定

     編輯:PHP 相關知識

三大使用場景

場景關鍵字位置生命週期/作用域
靜態區域變數函數/方法內部請求級別持久化,跨呼叫保持值
靜態屬性類別內部 static $var類別級別,所有實例共享
靜態方法類別內部 static function()類別級別,無 $this,不可存取非靜態成員

場景一:靜態區域變數 (函數記憶)

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

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

// 實用案例:單例模式簡易版
function getDatabase() {
    static $pdo = null;
    if ($pdo === null) {
        $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    }
    return $pdo;
}

// 遞迴計數器
function recursive($n) {
    static $depth = 0;
    $depth++;
    if ($n <= 0) { $depth--; return; }
    recursive($n - 1);
    $depth--;
}
?>

場景二:靜態屬性與方法

<?php
class Config {
    // 靜態屬性:類別級別共享
    private static $settings = [];
    private static $instance = null;
    
    // 私有建構子 (單例)
    private function __construct() {}
    
    // 靜態方法:工廠/存取器
    public static function getInstance(): self {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public static function set(string $key, $value): void {
        self::$settings[$key] = $value;
    }
    
    public static function get(string $key, $default = null) {
        return self::$settings[$key] ?? $default;
    }
    
    // 靜態方法不可使用 $this
    // public static function bad() { $this->settings = []; } // Fatal Error
}

// 使用
Config::set('app.name', 'MyApp');
echo Config::get('app.name'); // MyApp
$config = Config::getInstance();
?>

關鍵差異:self vs static (延遲靜態綁定 LSB)

<?php
class ParentClass {
    public static $who = 'Parent';
    
    public static function sayWho() {
        echo "self: " . self::$who . "\n";     // 編譯期綁定 -> Parent
        echo "static: " . static::$who . "\n"; // 執行期綁定 -> 實際調用類別
    }
}

class ChildClass extends ParentClass {
    public static $who = 'Child';
}

ParentClass::sayWho(); 
// self: Parent
// static: Parent

ChildClass::sayWho();  
// self: Parent  (self 綁定寫死在 ParentClass)
// static: Child (static 綁定到實際調用的 ChildClass)
?>

實戰:ActiveRecord 基類 (LSB 核心應用)

<?php
abstract class Model {
    protected static string $table = '';
    
    // 靜態工廠:建立查詢構建器
    public static function query(): QueryBuilder {
        return new QueryBuilder(static::$table); // LSB: 子類別的 table
    }
    
    // 靜態查找
    public static function find(int $id): ?static {
        $builder = static::query(); // LSB: 子類別的 query()
        return $builder->where('id', $id)->first();
    }
    
    // 靜態建立
    public static function create(array $attributes): static {
        $builder = static::query();
        $id = $builder->insert($attributes);
        return static::find($id);
    }
}

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

class Post extends Model {
    protected static string $table = 'posts';
}

// 使用
$user = User::find(1);      // 查 users 表
$post = Post::find(1);      // 查 posts 表
$newUser = User::create(['name' => 'Alice']); // 寫 users 表
?>

靜態成員存取語法總結

位置存取靜態屬性存取靜態方法存取實例屬性存取實例方法
類別外部Class::$propClass::method()需實例 $obj->prop需實例 $obj->method()
類別內部 (非靜態)self::$prop / static::$propself::method() / static::method()$this->prop$this->method()
類別內部 (靜態方法)self::$prop / static::$propself::method() / static::method()❌ 不可直接存取❌ 不可直接存取
父類別存取子類別靜態static::$prop (LSB)static::method() (LSB)N/AN/A

繼承與覆寫規則

  • 子類別可覆寫父類別靜態屬性/方法
  • parent:: 存取父類別靜態成員
  • static:: 執行期解析到實際類別 (LSB)
  • self:: 編譯期解析到定義該方法的類別
  • 介面可宣告靜態方法 (PHP 8.1+),但介面靜態方法無 LSB 行為

常見誤區與避坑

誤區正確認知
靜態方法可用 $this Fatal Error,靜態方法無物件上下文
靜態屬性屬於實例屬於類別,所有實例共享同一記憶體位址
static 變數在類別層級函數內 static 是函數級,類別內 static 是類別級
介面可定義靜態屬性介面只能定義常數 (PHP 8.1 前) 或靜態方法 (PHP 8.1+)
Trait 中 static 變數共享每個使用 Trait 的類別有獨立副本 (非共享)

效能與記憶體考量

  • 靜態成員存活於整個請求週期 (PHP-FPM) 或進程生命週期 (Swoole)
  • 大量靜態資料會佔用記憶體,長期運行進程需注意洩漏
  • 單例模式、快取、註冊表模式常用靜態屬性
  • 測試時靜態狀態污染需在 tearDown 重置

現代替代方案

需求傳統 static現代替代
單例/全域存取static $instance依賴注入容器 (PSR-11)
配置管理static $settings配置物件 + 容器綁定
快取static $cache = []Redis/Memcached/PSR-16 Cache
資料庫連線static $pdo連線池 / 容器管理
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved