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

PHP 面向對象編程核心精講:類聲明、構造析構、魔術方法與內存模型

     編輯:PHP 相關知識

PHP 面向對象編程核心精講:類聲明、構造析構、魔術方法與內存模型

PHP 5 引入完整對象模型,PHP 7/8 進一步優化性能與類型系統。掌握類聲明規範、構造/析構函數、魔術方法、內存分配機制,是編寫可維護、高性能 PHP 代碼的基石。本文系統梳理 OOP 核心知識點,對比 Java 概念,提供生產級代碼模式。

一、類聲明與對象初始化規範

1. 成員屬性聲明:可見性關鍵字

<?php
class Person
{
    public string $name = '';      // 公開:任意位置訪問
    protected int $age = 0;        // 受保護:本類 + 子類
    private string $idCard = '';   // 私有:僅本類
    // var $oldStyle = 'deprecated'; // PHP 4 風格,已棄用,勿用
}
  • 嚴格類型聲明:PHP 7.4+ 支持類型屬性(string $name),構造函數中必須初始化或標記 ?string 可空。
  • 唯讀屬性:PHP 8.1+ public readonly string $uuid; 初始化後不可修改,替代 getter-only 模式。

2. 文件組織:PSR-4 自動加載

  • 一個文件定義一個類,文件名 = 類名(Person.php)
  • 命名空間對應目錄結構:App\Models\Person → app/Models/Person.php
  • Composer 自動加載:"psr-4": {"App\\": "app/"}

3. 對象創建與內存分配

$p1 = new Person(); // 堆內存分配對象,棧內存存放引用變量 $p1
$p1->name = '張三';

關鍵點:PHP 使用引用計數 GC,對象賦值 $p2 = $p1 為引用拷貝(指向同一堆對象),clone $p1 才創建新對象(淺拷貝,需 __clone() 深拷貝)。

二、構造函數與析構函數

1. 構造函數 __construct()

  • PHP 4:與類同名方法;PHP 5+ 統一使用 __construct(),優點:重命名類無需改構造函數名。
  • 作用:依賴注入、屬性初始化、建立不變約束。
  • 參數提升(PHP 8.0+):public function __construct(public string $name) {} 自動創建並賦值同名屬性。
<?php
class Person
{
    public function __construct(
        public string $name = '',
        public int $age = 0,
        public string $gender = '男'
    ) {}

    public function say(): void
    {
        echo "我是 {$this->name},{$this->age} 歲,{$this->gender}。\n";
    }
}

$p1 = new Person('張三', 20, '女');
$p2 = new Person('李四', 25);      // 使用默認 gender
$p3 = new Person('王五');          // 使用默認 age、gender
$p1->say(); $p2->say(); $p3->say();

2. 析構函數 __destruct()

  • 對象被銷毀前自動調用(引用計數歸零、腳本結束、显式 unset())。
  • 用途:關閉資源(DB 連接、文件句柄、Socket)、釋放鎖、記錄日誌。
  • 注意:腳本強制終止(exit、致命錯誤、SIGKILL)不會調用析構函數。關鍵資源必須配合 register_shutdown_function() 或上下文管理器模式保障。
<?php
class Person
{
    public function __construct(public string $name) {}
    public function __destruct()
    {
        echo "{$this->name} 再見!\n"; // 腳本結束時輸出
    }
}
$p = new Person('張三');
$p = null; // 立即觸發析構:張三 再見!

三、魔術方法全景圖

內存區存儲內容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

四、$this 動態綁定機制(核心難點)

<?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 始終指向 當前方法執行時的實例對象,而非方法定義所在的類。這是多態的基石。

五、最佳實踐速查表

| 场景 | 推薦模式 | 關鍵點 | |---|---|---| | 構造參數過多 | Builder 模式 / 參數對象 | 避免構造函數膨脹 | | 不可變對象 | readonly 屬性 + 無 setter | PHP 8.1+ 原生支持 | | 資源管理 | 上下文管理器 / __destruct + register_shutdown_function | 保證釋放 | | 序列化安全 | __sleep 白名單 / __serialize | 防止敏感數據洩露 | | 動態方法 | __call + 文檔註解 @method | IDE 提示支持 | | 調試輸出 | __debugInfo 過濾密碼/Token | 生產環境安全 |

深入理解 PHP 對象模型的內存語義、生命周期鉤子、動態綁定機制,能讓你設計出符合 SOLID 原則、性能優異、易於測試與維護的領域模型。建議將常用魔術方法模式封裝為 Trait(如 ArrayAccessProxy、SerializableEntity),在實體類中復用,減少樣板代碼。

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