基本類別結構
name} is crying...\n";
}
// 建構子:new 時自動呼叫
public function __construct(string $name = 'Anonymous', int $age = 0) {
$this->name = $name;
$this->age = $age;
echo "{$this->name} 對象生成啦\n";
}
// 解構子:物件銷毀時自動呼叫
public function __destruct() {
echo "{$this->name} 對象銷毀啦\n";
}
}
// 實例化
$leo = new Human('Leo', 25);
$tim = new Human('Tim', 18);
echo "--- 手動銷毀 ---\n";
unset($leo); // 顯式銷毀
echo "--- 腳本結束隱式銷毀 ---\n";
// $tim 此處自動銷毀
/* 輸出順序:
Leo 對象生成啦
Tim 對象生成啦
--- 手動銷毀 ---
Leo 對象銷毀啦
--- 腳本結束隱式銷毀 ---
Tim 對象銷毀啦
*/
存取修飾符
| 修飾符 | 類別內部 | 繼承類別 | 外部程式碼 |
public | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ❌ |
private | ✅ | ❌ | ❌ |
class Example {
public $pub = 1;
protected $pro = 2;
private $pri = 3;
public function show() {
echo $this->pub; // ✅
echo $this->pro; // ✅
echo $this->pri; // ✅
}
}
class Child extends Example {
public function test() {
echo $this->pub; // ✅
echo $this->pro; // ✅
// echo $this->pri; // ❌ Fatal Error
}
}
$obj = new Example();
echo $obj->pub; // ✅
// echo $obj->pro; // ❌
// echo $obj->pri; // ❌
靜態成員 vs 實例成員
class Counter {
public static int $staticCount = 0; // 類別層級
public int $instanceCount = 0; // 物件層級
public function increment(): void {
self::$staticCount++; // 靜態用 self::
$this->instanceCount++; // 實例用 $this->
}
public static function getStatic(): int {
return self::$staticCount;
}
}
$a = new Counter();
$b = new Counter();
$a->increment();
$b->increment();
echo Counter::getStatic(); // 2 (共享)
echo $a->instanceCount; // 1 (獨立)
echo $b->instanceCount; // 1 (獨立)
建構子進階用法
1. 建構子提升屬性
// PHP 8.0+
class User {
public function __construct(
public string $name,
public string $email,
protected string $passwordHash,
private int $id = 0
) {}
}
$user = new User('Leo', 'leo@example.com', 'hashed_pwd');
echo $user->name; // Leo
2. 多建構子模式 (靜態工廠方法)
class DateTime {
private int $timestamp;
private function __construct(int $ts) {
$this->timestamp = $ts;
}
public static function now(): self {
return new self(time());
}
public static function fromString(string $date): self {
return new self(strtotime($date));
}
public static function fromTimestamp(int $ts): self {
return new self($ts);
}
}
$dt1 = DateTime::now();
$dt2 = DateTime::fromString('2024-01-01');
$dt3 = DateTime::fromTimestamp(1704067200);
3. 依賴注入
class OrderService {
public function __construct(
private PaymentGateway $gateway,
private LoggerInterface $logger,
private EventDispatcher $dispatcher
) {}
}
解構子最佳實踐
- 釋放資源:關閉資料庫連線、檔案控制代碼、cURL handle
- 不要在解構子拋出例外 (PHP 會忽略並產生 Fatal Error)
- 避免執行耗時操作 (關閉連線通常足夠)
- 循環參考時解構順序不確定,考慮
__destruct 內 gc_collect_cycles()
物件複製與複製控制
class Document {
public string $title;
private array $metadata;
public function __construct(string $title) {
$this->title = $title;
$this->metadata = ['created' => time()];
}
// 淺拷貝預設行為:基本型別複製,物件參考同一實例
// 深拷貝自定義
public function __clone() {
$this->metadata = $this->metadata; // 陣列自動深拷貝
// 若有物件屬性:$this->child = clone $this->child;
}
}
$doc1 = new Document('Report');
$doc2 = clone $doc1;
$doc2->title = 'Report v2';
魔術方法總覽
| 方法 | 觸發時機 | 常見用途 |
__construct | new Class() | 初始化、依賴注入 |
__destruct | 物件銷毀 | 資源釋放 |
__call | 呼叫不可見方法 | 動態代理、委派 |
__callStatic | 靜態呼叫不可見方法 | 流式介面、工廠 |
__get | 讀取不可見屬性 | 唯讀屬性、延遲載入 |
__set | 寫入不可見屬性 | 驗證、觸發事件 |
__isset | isset($obj->prop) | 虛擬屬性存在性 |
__unset | unset($obj->prop) | 清理關聯資源 |
__sleep | serialize() | 指定序列化屬性 |
__wakeup | unserialize() | 重建資源連線 |
__serialize | serialize() (PHP 7.4+) | 新序列化協定 |
__unserialize | unserialize() (PHP 7.4+) | 新反序列化協定 |
__toString | 物件當字串用 | 除錯、模板輸出 |
__invoke | $obj() | 可呼叫物件、閉包替代 |
__clone | clone $obj | 深拷貝控制 |
__debugInfo | var_dump() | 自訂除錯輸出 |