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

PHP static 靜態屬性與方法完整指南:從入門到進階

     編輯:PHP 相關知識

前言

在物件導向開發中,並非所有類別都需要實例化多個對象。工具類、配置管理、單例服務等場景,使用 static 關鍵字定義靜態屬性與方法,可避免 new 開銷、簡化調用語法、實現跨請求的狀態共享。本文系統梳理 PHP static 的語法規則、內部調用、繼承行為與實戰模式。

基礎語法:直接類名調用

<?php
class HelloWorld {
    public static function say() {
        return 'Hello World!';
    }
}

// 直接透過類名調用,無需實例化
echo HelloWorld::say(); // 輸出:Hello World!
?>

雖然未加 static 的實例方法在 PHP 也能靜態調用(HelloWorld::say()),但會觸發 E_DEPRECATED 警告且語意不清,**強烈建議明確加上 static**。

類內部調用:self:: 與 static::

<?php
class Foo {
    private static function internal() {
        return 'internal';
    }

    public static function publicApi() {
        // 同類靜態方法調用
        echo self::internal(); // 輸出:internal
    }
}

Foo::publicApi();
?>
  • self:::綁定**定義該方法的類別**(早期靜態綁定)
  • static:::綁定**實際調用的類別**(晚期靜態綁定,LSB),PHP 5.3+ 支援

靜態屬性:類級別的共享狀態

<?php
class Counter {
    public static $count = 0;

    public static function increment() {
        self::$count++;
    }
}

Counter::increment();
Counter::increment();
echo Counter::$count; // 輸出:2
?>

靜態屬性屬於**類別本身**,不屬於某個實例。所有實例、靜態調用共享同一份記憶體空間,生命週期貫穿整個腳本執行期。

繼承與靜態成員:關鍵行為差異

方法覆寫

<?php
class ParentClass {
    public static function who() { echo 'Parent'; }
}
class ChildClass extends ParentClass {
    public static function who() { echo 'Child'; }
}
ChildClass::who(); // 輸出:Child
?>

父類調用:必須用 parent::

<?php
class ParentClass {
    public static function greet() { return 'Hello from Parent'; }
}
class ChildClass extends ParentClass {
    public static function greet() {
        // 錯誤:self::greet() 會調用 ChildClass::greet() 導致無限遞歸
        // 正確:
        return parent::greet() . ' -> Child';
    }
}
echo ChildClass::greet(); // 輸出:Hello from Parent -> Child
?>

靜態屬性繼承:各類別獨立一份

<?php
class Base {
    public static $val = 'base';
}
class DerivedA extends Base {}
class DerivedB extends Base {}

DerivedA::$val = 'A';
DerivedB::$val = 'B';

echo Base::$val;    // base
echo DerivedA::$val; // A
echo DerivedB::$val; // B
?>

**關鍵點**:子類**首次**對靜態屬性賦值時,會在子類作用域建立獨立副本,不再影響父類與其他兄弟類。這與 Java/C# 行為一致。

實戰模式:常數分組與狀態機

<?php
class OrderStatus {
    public const PENDING   = 0;
    public const PAID      = 1;
    public const SHIPPED   = 2;
    public const COMPLETED = 3;
    public const CANCELLED = -1;

    // 靜態方法封裝業務邏輯
    public static function canCancel(int $status): bool {
        return in_array($status, [self::PENDING, self::PAID], true);
    }
}

// 使用
$status = OrderStatus::PAID;
if (OrderStatus::canCancel($status)) {
    // 允許取消
}
?>

PHP 8.1+ 推薦改用 enum 實現更強類型的狀態機,但 static const 組合在舊版本仍是最佳實踐。

進階:Late Static Binding (LSB) 實戰

<?php
class Model {
    protected static $table = 'base_table';

    public static function getTable(): string {
        return static::$table; // LSB:取調用類的 $table
    }
}

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

echo User::getTable(); // users
echo Post::getTable(); // posts
?>

若改用 self::$table,所有子類都會回傳 base_table。LSB 是 ActiveRecord、Repository 等基礎框架類的核心機制。

效能與記憶體考量

  • 靜態方法調用比實例方法快(省去實例化、$this 綁定)
  • 靜態屬性常駐記憶體,**避免存放大型資料結構**(如巨大陣列、檔案句柄)導致記憶體洩漏
  • 單元測試時靜態狀態難以隔離,建議依賴注入替代全域靜態服務

總結

場景推薦寫法
工具函數、純邏輯運算public static function
類級別配置、快取、計數器public static $property
基礎類定義預設值,子類覆寫protected static $prop + static::$prop (LSB)
子類調用父類靜態方法parent::method()
常數分組public const (PHP 7.1+) 或 public static

善用 static 能讓代碼更簡潔、效能更高,但需謹記「靜態即全域」的副作用,避免濫用導致耦合度過高、測試困難。

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