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

PHP 5 靜態成員深度解析:屬性、方法與常數的正確使用

     編輯:PHP 綜合知識

PHP 5 引入靜態關鍵字(static),允許定義屬於類別而非實例的屬性、方法與常數。本文深入解析靜態成員特性、記憶體模型、呼叫語法、常見誤區與最佳實踐。

核心概念對比

特性實例成員靜態成員
所屬具體物件實例類別本身
記憶體每個實例獨佔一份全程式共享一份
存取方式$obj->prop、$obj->method()Class::$prop、Class::method()
$this 可用性可用不可用(靜態方法內無 $this)
繼承行為多型覆寫靜態綁定(預設),可用 static:: 延遲靜態綁定
常數不支援const 隱含靜態

靜態屬性

class Counter {
    private static $count = 0;  // 僅類別可見
    public static $publicCount = 0; // 公開存取

    public function __construct() {
        self::$count++;         // 類別內部用 self::
        static::$publicCount++; // 也可用 static:: (LSB)
    }

    public static function getCount() {
        return self::$count;
    }
}

// 使用
$c1 = new Counter();
$c2 = new Counter();
echo Counter::$publicCount; // 2
echo Counter::getCount();   // 2

關鍵點

  • 初始化:宣告時必須給定字面值(標量、陣列常數),不能用運算式或函數呼叫。
  • 可見性:支援 public/protected/private。
  • 繼承:子類別若重新宣告同名靜態屬性,會遮蔽父類別屬性(非覆寫),各自獨立儲存。

靜態方法

class Utils {
    public static function formatPrice($amount, $currency = 'TWD') {
        return $currency . number_format($amount, 2);
    }

    // 靜態方法可呼叫其他靜態成員
    public static function log($msg) {
        self::writeLog(date('Y-m-d H:i:s') . ' ' . $msg);
    }

    private static function writeLog($line) {
        error_log($line, 3, __DIR__ . '/app.log');
    }
}

echo Utils::formatPrice(1234.5); // TWD1,234.50

靜態方法 vs 實例方法呼叫差異

class Demo {
    public function instanceMethod() {
        echo "Instance: " . ($this ? 'has $this' : 'no $this') . "\n";
    }
    public static function staticMethod() {
        echo "Static: " . (isset($this) ? 'has $this' : 'no $this') . "\n";
    }
}

$obj = new Demo();
$obj->instanceMethod(); // Instance: has $this
$obj->staticMethod();   // Static: no $this  (PHP 7+ 嚴格模式下會 Deprecated)
Demo::staticMethod();   // Static: no $this
Demo::instanceMethod(); // Deprecated: Non-static method called statically

類別常數

class Config {
    const VERSION = '2.1.0';
    const MAX_RETRY = 3;
    const DEFAULT_OPTS = ['timeout' => 5, 'retry' => true]; // PHP 5.6+ 支援陣列常數
}

echo Config::VERSION; // 2.1.0
// Config::VERSION = '3.0'; // Fatal: Cannot override constant

常數隱含 public static,不可變更,繼承時子類別可定義同名常數覆蓋。

延遲靜態綁定 (Late Static Binding, LSB)

PHP 5.3+ 引入 static:: 關鍵字,解決繼承中靜態方法呼叫的綁定問題:

class ParentClass {
    public static function who() { echo __CLASS__ . "\n"; }
    public static function test() { self::who(); }   // 編譯期綁定 ParentClass
    public static function testLSB() { static::who(); } // 執行期綁定實際調用類別
}

class ChildClass extends ParentClass {
    public static function who() { echo __CLASS__ . "\n"; }
}

ParentClass::test();    // ParentClass
ParentClass::testLSB(); // ParentClass
ChildClass::test();     // ParentClass (self:: 綁定父類)
ChildClass::testLSB();  // ChildClass (static:: 綁定子類)

常見誤區與最佳實踐

誤區正確做法
靜態方法中使用 $this改用 self:: 或 static:: 存取靜態成員
將大量狀態存放在靜態屬性(全域狀態)改用依賴注入、服務容器、單例模式管理共享狀態
靜態屬性初始化用 new Object()PHP 8.1+ 支援 static $obj = new Class();,舊版改用靜態建構子模式
濫用靜態方法作為工具函數集考慮命名空間函數、單一職責服務類別
忽略 LSB 導致繼承失效需多型行為時統一使用 static::

實際應用場景

  • 計數器/快取/註冊表:單一共享狀態
  • 工廠方法:User::createFromRequest($request)
  • 設定常數:AppConfig::DB_HOST
  • 單例模式:private static $instance; public static function getInstance()
  • 輔助函數:Str::slug(), Arr::pluck()

善用靜態成員能簡化共享資料存取,但過度使用會導致耦合度高、難以測試。遵循「預設實例化、必要時靜態」原則。

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