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

PHP 面向物件程式設計 (下):多型、序列化與進階技巧

     編輯:PHP 相關知識

PHP OOP 核心進階:多型自然支援、序列化機制與設計模式基礎

PHP 對多型提供原生支援:執行時根據物件實際類型決定呼叫哪個方法,無需像 C++ 虛函數表那樣編譯期綁定。序列化則提供物件狀態持久化能力,但需注意其限制與安全風險。

多型實作範例

<?php
abstract class Shape {
    abstract public function draw(): void;
    abstract public function area(): float;
}

class Circle extends Shape {
    private $radius;
    public function __construct(float $radius) { $this->radius = $radius; }
    public function draw(): void { echo "繪製圓形 (r={$this->radius})\n"; }
    public function area(): float { return M_PI * $this->radius ** 2; }
}

class Rectangle extends Shape {
    private $width, $height;
    public function __construct(float $w, float $h) { $this->width = $w; $this->height = $h; }
    public function draw(): void { echo "繪製矩形 ({$this->width}x{$this->height})\n"; }
    public function area(): float { return $this->width * $this->height; }
}

class Board {
    public function niceDrawing(Shape $shape): void {
        // 多型: $shape 實際類型決定呼叫哪個 draw()
        $shape->draw();
        echo "面積: " . $shape->area() . "\n";
    }
}

$board = new Board();
$board->niceDrawing(new Circle(5));      // 繪製圓形, 面積: 78.54
$board->niceDrawing(new Rectangle(4,6)); // 繪製矩形, 面積: 24
?>

關鍵概念

  • 介面/抽象類別定義契約:Shape 定義 draw()、area(),強制子類別實作。
  • 型別提示:Shape $shape 確保傳入物件符合契約 (PHP 7.0+)。
  • 執行時綁定:PHP 為動態語言,方法查找在呼叫時根據物件實際類別進行,天然支援多型。

序列化

<?php
class User {
    public $id;
    public $name;
    private $passwordHash; // 敏感資料不應序列化
    private $dbConnection; // 資源型別無法序列化

    public function __construct($id, $name, $passwordHash) {
        $this->id = $id;
        $this->name = $name;
        $this->passwordHash = $passwordHash;
    }

    // 自訂序列化:排除敏感/資源屬性
    public function __sleep(): array {
        return ['id', 'name']; // 僅回傳需序列化的屬性名稱
    }

    // 反序列化還原
    public function __wakeup(): void {
        // 重新建立資料庫連線、載入密碼雜湊等
        // $this->dbConnection = new PDO(...);
    }

    // PHP 7.4+ 新介面 (推薦)
    // public function __serialize(): array { return ['id'=>$this->id, 'name'=>$this->name]; }
    // public function __unserialize(array $data): void { $this->id=$data['id']; $this->name=$data['name']; }
}

$user = new User(1, 'John', '$2y$10$...');
$serialized = serialize($user);
echo $serialized; // O:4:"User":2:{s:2:"id";i:1;s:4:"name";s:4:"John";}

$restored = unserialize($serialized);
echo $restored->name; // John
?>

序列化最佳實踐與風險

主題建議
敏感資料實作 __sleep 排除密碼、Token、金鑰;或改用 JSON 序列化 (json_encode) 手動控制輸出欄位
資源型別PDO、Socket、GD 影像資源無法序列化,__wakeup 中重建
版本相容類別結構更 (增減屬性) 導致反序列化失敗,建議加入版本號屬性並在 __wakeup 遷移
安全性絕不 unserialize 使用者可控輸入,會導致物件注入 (POP 鏈) 攻擊,改用 json_decode、igbinary、msgpack
效能igbinary、msgpack 二進位格式比內建 serialize 快 2-5 倍、體積小 30-50%
Session 儲存PHP Session 預設使用 serialize,大型物件會拖慢 Session 讀寫,建議只存 ID、必要資料

進階 OOP 技巧

  1. Trait 程式碼複用:單一繼承限制下橫向複用邏輯 (如 SoftDeletes, Loggable)。
  2. 魔術方法:__call/__callStatic (動態方法)、__get/__set (屬性存取攔截)、__invoke (可呼叫物件)。
  3. 匿名類別:new class implements Logger { ... } 臨時建立一次性實作 (PHP 7.0+)。
  4. 靜態延遲綁定:static:: 在繼承體系中指向實際被呼叫的類別 (PHP 5.3+)。
  5. 唯讀屬性:readonly (PHP 8.1+) 確保初始化後不可變更。

SOLID 原則在 PHP 中的落地

  • S 單一職責:每個類別只負責一項業務邏輯 (如 UserRepository 只管資料存取)。
  • O 開放封閉:擴充功能不修改既有代碼 (用介面 + 多型、裝飾器模式)。
  • L 里氏替換:子類別可替換父類別不破壞行為 (嚴格遵守契約、前置條件不強化、後置條件不弱化)。
  • I 介面隔離:多個小介面優於單一大介面 (LoggerInterface, CacheableInterface)。
  • D 依賴反轉:依賴抽象不依賴具體 (建構子注入 PDO 介面而非具體類別)。

掌握多型、序列化邊界與 SOLID 原則,能寫出可維護、可測試、可擴充的 PHP 物件導向代碼,是從「寫腳本」邁向「軟體工程」的關鍵。

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