以
::靜態方式呼叫非靜態方法時,方法內的$this並非指向定義該方法的類別,而是由呼叫時的上下文決定。
<?php
class TestClass1 {
public $normal_v = 'normal_v from TestClass1';
public static $STATIC_V = 'STATIC_V from TestClass1';
public function test_func1() {
echo $this->normal_v . '
' . self::$STATIC_V;
}
}
class TestClass2 {
public $normal_v = 'normal_v from TestClass2';
public static $STATIC_V = 'STATIC_V from TestClass2';
public function test_func2() {
TestClass1::test_func1(); // 靜態呼叫非靜態方法
}
}
$t2 = new TestClass2();
$t2->test_func2();
normal_v from TestClass2
STATIC_V from TestClass1
| 表達式 | 解析規則 | 結果 |
|---|---|---|
$this->normal_v | $this 來自呼叫端 $t2(TestClass2 實例) | TestClass2 的屬性 |
self::$STATIC_V | self 在編譯期綁定到定義類別 TestClass1 | TestClass1 的靜態屬性 |
static::$STATIC_V (晚期靜態綁定) | 若改用 static::,則綁定到呼叫端 TestClass2 | TestClass2 的靜態屬性 |
歷史遺留:PHP 4 時代無 static 關鍵字,所有方法預設皆可靜態呼叫。PHP 5 保留相容性,並引入 E_STRICT(PHP 5.3~7.x)與 E_DEPRECATED(PHP 8.0+)警告:
Deprecated: Non-static method TestClass1::test_func1() should not be called statically
php.ini 設定 error_reporting = E_ALL,升級為錯誤。$this → public function(實例方法)$this、只操作靜態屬性 → public static functionstatic::$prop 而非 self::$prop。<?php
class ServiceA {
public function doWork() { /* ... */ }
}
class ServiceB {
private $serviceA;
public function __construct(ServiceA $a) { $this->serviceA = $a; }
public function execute() {
$this->serviceA->doWork(); // 正確:實例呼叫實例方法
}
}
PHP 允許靜態呼叫非靜態方法是為了向下相容,但會導致 $this 指向呼叫端實例,造成極難除錯的行為。現代 PHP(7.4+)開發應嚴格區分實例與靜態方法,並啟用嚴格錯誤報告杜絕此類寫法。