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

Zend Engine 演進史:從 PHP 3 的「語法糖」到 PHP 5 的物件控制代碼機制

     編輯:PHP 綜合知識

前言:Zeev Suraski 親述 Zend 引擎物件模型演變

本文節選自《Core PHP Programming》第 15 節,由 PHP 核心開發者 Zeev Suraski 撰寫,Haohappy 翻譯整理。詳細記錄了 PHP 從純程序語言踏上物件導向之路的關鍵里程碑:PHP 3 的初步嘗試、PHP 4 引入參考機制卻帶來「WTMA 綜合症」、PHP 5 徹底重寫物件模型採用 Object Store 與控制代碼,實現真正的參考語意與高效能。

一、PHP 3:物件只是「好看的陣列」

1997 年夏天開發 PHP 3 時,完全沒有物件導向計畫。1997/08/27 晚間,PHP 3 Alpha 版臨時加入類別支援。當時的物件模型極其簡陋:

  • 物件本質上就是關聯陣列的另一種寫法:$foo->bar 取代 $foo['bar']。
  • 成員函數僅是儲存在陣列中的函數名稱,呼叫時需手動傳遞 $this。
  • 完全沒有封裝、繼承、多型等 OOP 核心特性。

程式碼對比:

<?php
// PHP 3 物件寫法
class Example {
    var $value = "some value";
    function PrintValue() { print $this->value; }
}
$obj = new Example();
$obj->PrintValue();

// PHP 3 結構化寫法 (完全等效)
function PrintValue($arr) { print $arr["value"]; }
function CreateExample() {
    return ["value" => "some value", "PrintValue" => "PrintValue"];
}
$arr = CreateExample();
$arr["PrintValue"]($arr); // 間接呼叫
?>

結論:PHP 3 的物件只是「語法糖」,無法支援設計模式與複雜 OOP 架構。

二、PHP 4:引入參考,卻陷入「WTMA 綜合症」

PHP 4 引入參考 概念 (&),允許多個變數指向同一記憶體位址,這是建立物件網絡的基礎。但 PHP 仍將物件視為普通資料類型:指派即複製。

經典失敗案例

<?php
class MyFoo {
    function MyFoo() {
        $this->me = &$this; // 建構子內建立自我參考
        $this->value = 5;
    }
    function setValue($val) { $this->value = $val; }
    function getValue() { return $this->value; }
    function getValueFromMe() { return $this->me->value; }
}

function CreateObject($type) {
    switch ($type) {
        case "foo": $obj = new MyFoo(); break;
        case "bar": $obj = new MyBar(); break;
    }
    return $obj; // 回傳時複製物件!
}

$global_obj = CreateObject("foo");
$global_obj->setValue(7);
print $global_obj->getValue();        // 輸出 7
print $global_obj->getValueFromMe();  // 輸出 5 (!!)
?>

三大失敗原因

  1. 建構子結束時複製: new MyFoo() 回傳的是建構子內物件的副本,$this->me 仍指向原始物件,導致 $obj 與 $obj->me 脫節。
  2. 函數回傳再次複製: CreateObject 回傳 $obj 時再次複製,$global_obj 與 $global_obj->me 再次脫節。
  3. 回傳敘述破壞參考: return $obj 切斷了參考鏈結。

痛苦的解法:到處加 &

$obj =& new MyFoo();           // 28 行
$obj =& new MyBar();           // 31 行
$global_obj =& CreateObject("foo"); // 37 行
function &CreateObject($type) { ... } // 24 行

這就是著名的 WTMA (Way Too Many Ampersands) 綜合症 —— 程式碼滿是 &,極難維護。

三、PHP 5:徹底重寫,物件成為「第一類公民」

PHP 5 是第一個將物件視為獨特資料類型的版本。核心改變:

  • 物件永遠以參考傳遞,無需 &。
  • 只有明確要求才複製 (clone 關鍵字)。
  • 底層引入 Object Store (物件儲存區) 與 控制代碼 機制。

底層實作:zval 與 Object Store

PHP 5 同樣程式碼,移除所有 & 即完美運作

<?php
class MyFoo {
    function __construct() {
        $this->me = $this; // 無需 &,預設即參考
        $this->value = 5;
    }
    // ... 其他方法同前 ...
}

function CreateObject($type) {
    switch ($type) {
        case "foo": $obj = new MyFoo(); break; // 無需 &
        case "bar": $obj = new MyBar(); break;
    }
    return $obj; // 無需 &,回傳參考
}

$global_obj = CreateObject("foo"); // 無需 &
$global_obj->setValue(7);
print $global_obj->getValue();        // 7
print $global_obj->getValueFromMe();  // 7 ✓
?>

結語

Zend Engine 2 的物件模型改革,解決了 PHP 4 以來的核心痛點:

  1. 效能提升: 避免不必要的物件複製,減少記憶體佔用與 CPU 開銷。
  2. 語意清晰: 物件行為符合直覺 (參考語意),支援完整設計模式。
  3. 開發體驗: 擺脫 WTMA 綜合症,程式碼簡潔可讀。

這套基於 Object Store 與控制代碼的架構,奠定了現代 PHP (PHP 7/8 含 JIT) 高效能物件模型的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
PHP 4 及之前PHP 5
所有值 (含物件) 統一存於 zval 結構標量/陣列存 zval,物件存 Object Store
傳遞/回傳時複製整個 zvalzval 僅存物件指標 (handle),複製 zval 只複製指標
修改副本不影響原物件所有指標指向同一 Object Store 實體,修改即時生效