self 代表**當前定義的類**,用於存取**靜態屬性、常數、靜態方法**。它在**編譯時綁定**,不指向任何實例化物件。
self::$staticProperty
self::CONSTANT
self::staticMethod()
必須配合 ::(作用域解析操作符)使用。
<?php
class Counter {
private static $firstCount = 0; // 類層級,所有實例共享
private $lastCount; // 實例層級,各自獨立
public function __construct() {
// 使用 self 存取靜態屬性
$this->lastCount = ++self::$firstCount;
}
public function printLastCount() {
echo $this->lastCount . "\n";
}
}
$obj1 = new Counter(); // self::$firstCount = 1, $obj1->lastCount = 1
$obj1->printLastCount(); // 1
$obj2 = new Counter(); // self::$firstCount = 2, $obj2->lastCount = 2
$obj2->printLastCount(); // 2
$obj3 = new Counter(); // self::$firstCount = 3, $obj3->lastCount = 3
$obj3->printLastCount(); // 3
echo "總計建立: " . Counter::$firstCount; // 錯誤:private 不可外部存取
// 需提供公共靜態方法
?>
self 解析為書寫該代碼的類,不隨繼承變化。self->property 存取實例屬性。self:: 存取靜態成員。<?php
class Base {
public static $name = 'Base';
public static function whoSelf() {
echo "self: " . self::$name . "\n"; // 永遠指向 Base
}
public static function whoStatic() {
echo "static: " . static::$name . "\n"; // 指向實際調用類
}
}
class Child extends Base {
public static $name = 'Child';
}
Base::whoSelf(); // self: Base
Base::whoStatic(); // static: Base
Child::whoSelf(); // self: Base ← 編譯時綁定在 Base
Child::whoStatic(); // static: Child ← 晚期靜態綁定
?>
<?php
abstract class Model {
protected static $table = 'base';
// 使用 static 獲取子類表名
public static function table() {
return static::$table;
}
// 使用 self 獲取基類預設連線
protected static function getDefaultConnection() {
return self::$pdo ??= new PDO('sqlite::memory:');
}
}
class User extends Model {
protected static $table = 'users';
}
class Post extends Model {
protected static $table = 'posts';
}
echo User::table(); // users(static 解析到 User)
echo Post::table(); // posts
?>
| 特性 | self | $this |
|---|---|---|
| 指向 | 當前類(靜態) | 當前實例(動態) |
| 存取成員 | 靜態屬性/常數/方法 | 實例屬性/方法 |
| 語法 | self::$prop、self::CONST、self::method() | $this->prop、$this->method() |
| 綁定時機 | 編譯時 | 執行時 |
| 繼承行為 | 固定在定義處類 | 隨實例類型變化 |
| 可用位置 | 靜態/非靜態方法 | 僅非靜態方法 |
class Foo {
public $x = 1;
public function bar() {
echo self::$x; // Error: Access to undeclared static property
}
}
class Foo {
public static function bar() {
echo $this->x; // Error: Using $this when not in object context
}
}
self vs static 範例。<?php
class User {
private static $instances = [];
public readonly string $name;
private function __construct(string $name) {
$this->name = $name;
}
// 靜態工廠:單例模式變體
public static function getInstance(string $name): self {
return self::$instances[$name] ??= new self($name);
}
// 克隆禁止
private function __clone() {}
public function __wakeup() { throw new Exception("不可反序列化"); }
}
$u1 = User::getInstance('Alice');
$u2 = User::getInstance('Alice');
$u3 = User::getInstance('Bob');
echo ($u1 === $u2) ? "同一實例\n" : "不同實例\n"; // 同一實例
echo ($u1 === $u3) ? "同一實例\n" : "不同實例\n"; // 不同實例
?>
self 是 PHP 類靜態成員的**編譯時入口**,配合 static(晚期靜態綁定)構成靜態多型的雙支柱。掌握 self 固定在定義類、static 隨調用類變化的本質差異,是設計可擴展基類、工廠模式、Active Record 等靜態導向架構的關鍵。