PHP 5 引入完整對象模型,PHP 7/8 進一步優化性能與類型系統。掌握類聲明規範、構造/析構函數、魔術方法、內存分配機制,是編寫可維護、高性能 PHP 代碼的基石。本文系統梳理 OOP 核心知識點,對比 Java 概念,提供生產級代碼模式。
<?php
class Person
{
public string $name = ''; // 公開:任意位置訪問
protected int $age = 0; // 受保護:本類 + 子類
private string $idCard = ''; // 私有:僅本類
// var $oldStyle = 'deprecated'; // PHP 4 風格,已棄用,勿用
}
string $name),構造函數中必須初始化或標記 ?string 可空。public readonly string $uuid; 初始化後不可修改,替代 getter-only 模式。Person.php)App\Models\Person → app/Models/Person.php"psr-4": {"App\\": "app/"}$p1 = new Person(); // 堆內存分配對象,棧內存存放引用變量 $p1
$p1->name = '張三';
| 內存區 | 存儲內容 | PHP 體現 | |
|---|---|---|---|
| 棧 | 局部變量、引用指針 | $p1 變量本身(zval 指向對象) | |
| 堆 | 對象實例數據、屬性值 | new Person() 分配的 object store | |
| 共享區 | 靜態屬性、類常量 | static $count; const TYPE = 1; | |
| 代碼段 | 方法字節碼、類定義 | opcache 緩存的編譯結果 |
| 方法 | 觸發時機 | 典型用途 | 返回值要求 |
|---|---|---|---|
__construct() | 實例化 new Class() | 初始化 | 無 |
__destruct() | 對象銷毀 | 清理資源 | 無 |
__call($name, $args) | 調用不可訪問/不存在的實例方法 | 代理、動態方法、DSL | 混合 |
__callStatic($name, $args) | 調用不可訪問/不存在的靜態方法 | 工廠、鏈式調用 | 混合 |
__get($name) | 讀取不可訪問/不存在的屬性 | 只讀代理、懶加載、計算屬性 | 混合 |
__set($name, $value) | 寫入不可訪問/不存在的屬性 | 驗證、日誌、關聯更新 | 無 |
__isset($name) | isset($obj->prop) / empty() | 虛擬屬性存在性判斷 | bool |
__unset($name) | unset($obj->prop) | 清理關聯數據 | 無 |
__sleep() | serialize($obj) | 指定序列化屬性、關閉資源 | array |
__wakeup() | unserialize($data) | 重建連接、初始化狀態 | 無 |
__serialize() | serialize() (PHP 7.4+) | 自定義序列化數據結構 | array |
__unserialize($data) | unserialize() (PHP 7.4+) | 自定義反序列化邏輯 | 無 |
__toString() | 對象作為字符串使用 echo $obj | 調試輸出、模板渲染 | string |
__invoke() | 對象作為函數調用 $obj() | 可調用對象、閉包替代 | 混合 |
__clone() | clone $obj | 深拷貝、重置 ID、複製關聯 | 無 |
__debugInfo() | var_dump($obj) (PHP 5.6+) | 控制調試輸出字段、隱藏敏感信息 | array |
__set_state($arr) | var_export() 導出類 | 還原靜態實例 | object |
<?php
class User
{
private array $data = [];
private array $hidden = ['password', 'token'];
public function __set(string $name, $value): void
{
if (in_array($name, $this->hidden, true)) {
throw new Exception("禁止直接設置敏感字段:$name");
}
$this->data[$name] = $value;
}
public function __get(string $name)
{
return $this->data[$name] ?? null;
}
public function __debugInfo(): array
{
return array_diff_key($this->data, array_flip($this->hidden));
}
}
$user = new User();
$user->name = '張三';
$user->email = 'zhang@example.com';
// $user->password = 'secret'; // 拋出異常
var_dump($user); // 不顯示 password、token
<?php
class A {
public function who() { echo 'A'; }
public function test() { $this->who(); }
}
class B extends A {
public function who() { echo 'B'; }
}
$b = new B();
$b->test(); // 輸出 B!因為 $this 綁定到實際調用對象 $b
鐵律:$this 始終指向 當前方法執行時的實例對象,而非方法定義所在的類。這是多態的基石。
readonly 屬性 + 無 setter | PHP 8.1+ 原生支持 |
| 資源管理 | 上下文管理器 / __destruct + register_shutdown_function | 保證釋放 |
| 序列化安全 | __sleep 白名單 / __serialize | 防止敏感數據洩露 |
| 動態方法 | __call + 文檔註解 @method | IDE 提示支持 |
| 調試輸出 | __debugInfo 過濾密碼/Token | 生產環境安全 |
深入理解 PHP 對象模型的內存語義、生命周期鉤子、動態綁定機制,能讓你設計出符合 SOLID 原則、性能優異、易於測試與維護的領域模型。建議將常用魔術方法模式封裝為 Trait(如 ArrayAccessProxy、SerializableEntity),在實體類中復用,減少樣板代碼。