PHP 從 5.0 重寫物件模型,支援完整的封裝、繼承、多型,並引入介面、抽象類、Trait、屬性提升、唯讀屬性、Enum 等現代特性。本文系統整理 PHP OOP 核心語法、設計原則、進階模式與最佳實踐。
<?php
declare(strict_types=1);
class User {
// 可見度:public / protected / private
// 唯讀屬性 (PHP 8.1+):初始化後不可修改
public readonly string $id;
public string $name;
protected string $email;
private string $passwordHash;
// 型別宣告 + 預設值
public function __construct(
string $id,
string $name,
string $email,
string $password
) {
$this->id = $id;
$this->name = $name;
$this->email = $email;
$this->passwordHash = password_hash($password, PASSWORD_DEFAULT);
}
// 方法
public function getEmail(): string {
return $this->email;
}
public function verifyPassword(string $password): bool {
return password_verify($password, $this->passwordHash);
}
// 魔術方法:序列化控制
public function __serialize(): array {
return ['id' => $this->id, 'name' => $this->name, 'email' => $this->email];
}
public function __unserialize(array $data): void {
$this->id = $data['id'];
$this->name = $data['name'];
$this->email = $data['email'];
// passwordHash 不序列化,反序列化後需重新設定
}
}
?>
<?php
abstract class Animal {
protected string $name;
public function __construct(string $name) {
$this->name = $name;
}
// 抽象方法:子類必須實作
abstract public function makeSound(): string;
// 普通方法可被覆寫
public function introduce(): string {
return "我是 {$this->name}";
}
// final 方法禁止覆寫
final public function getSpecies(): string {
return static::class;
}
}
class Dog extends Animal {
public function makeSound(): string {
return "汪汪!";
}
// 覆寫父類方法
public function introduce(): string {
return parent::introduce() . "," . $this->makeSound();
}
}
$dog = new Dog('旺財');
echo $dog->introduce(); // 我是旺財,汪汪!
?>
<?php
interface Payable {
public function pay(float $amount): bool;
}
interface Refundable {
public function refund(float $amount): bool;
}
// 多介面實作
class AlipayGateway implements Payable, Refundable {
public function pay(float $amount): bool { /* ... */ return true; }
public function refund(float $amount): bool { /* ... */ return true; }
}
class StripeGateway implements Payable {
public function pay(float $amount): bool { /* ... */ return true; }
}
// 多型:依賴介面而非具體類
function checkout(Payable $gateway, float $amount): void {
if ($gateway->pay($amount)) {
echo "付款成功\n";
}
}
checkout(new AlipayGateway(), 100.0);
checkout(new StripeGateway(), 50.0);
?>
<?php
trait Loggable {
protected function log(string $msg): void {
error_log("[" . date('c') . "] $msg");
}
}
trait Timestampable {
public readonly DateTimeImmutable $createdAt;
public ?DateTimeImmutable $updatedAt = null;
public function touch(): void {
$this->updatedAt = new DateTimeImmutable();
}
}
class Order {
use Loggable, Timestampable; // 多 Trait
public function __construct(public string $id) {
$this->createdAt = new DateTimeImmutable();
}
public function updateStatus(string $status): void {
$this->log("Order {$this->id} status changed to $status");
$this->touch();
}
}
?>
<?php
class Config {
public const VERSION = '1.0.0';
private static ?self $instance = null;
private array $settings = [];
private function __construct() {}
public static function getInstance(): self {
return self::$instance ??= new self(); // PHP 8.0 nullsafe 賦值
}
public function set(string $key, mixed $value): void {
$this->settings[$key] = $value;
}
public function get(string $key, mixed $default = null): mixed {
return $this->settings[$key] ?? $default;
}
}
// 晚期靜態綁定 (LSB)
class Base {
public static function who(): string {
return static::class; // 執行時解析為實際調用的類
}
}
class Child extends Base {}
echo Child::who(); // "Child"
?>
| 方法 | 觸發時機 | 常見用途 |
|---|---|---|
| __construct | new 實例化 | 初始化、依賴注入 |
| __destruct | 物件銷毀 | 釋放資源、關閉連線 |
| __call / __callStatic | 呼叫不存在/不可見方法 | 動態代理、流暢介面 |
| __get / __set / __isset / __unset | 存取不存在/不可見屬性 | 動態屬性、資料映射 |
| __toString | 物件當字串用 | 格式化輸出、ID 表示 |
| __invoke | 物件當函數呼叫 | 可呼叫物件、策略模式 |
| __serialize / __unserialize | 序列化/反序列化 (PHP 7.4+) | 控制序列化內容、替代 Serializable |
| __clone | clone 物件 | 深拷貝、重置 ID |
| __debugInfo | var_dump() | 隱藏敏感屬性、自定義顯示 |
public function __construct(public string $name) {}enum Status: string { case Draft = 'draft'; case Published = 'published'; }public function __construct(public readonly string $id) {}string&Countable|null。readonly class Dto { public function __construct(public string $a) {} }<?php
$user = new User('u1', 'John', 'john@example.com', 'secret');
// 原生 serialize (不推薦跨版本/語言)
$serialized = serialize($user);
$restored = unserialize($serialized);
// JSON (跨語言、可讀、無行為)
$json = json_encode($user, JSON_THROW_ON_ERROR); // 需實作 JsonSerializable
$restored = json_decode($json, true); // 陣列,非物件
// 推薦:專用 DTO + 序列化庫 (symfony/serializer, spatie/data-transfer-object)
?>
PHP OOP 已臻成熟,配合嚴格型別、靜態分析 (PHPStan Level 8+)、測試 (Pest/PHPUnit)、編碼標準 (PSR-12),可構建極高品質的企業級應用。關鍵在於:依賴介面、組合優於繼承、單一職責、不可變資料、領域建模。