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

深入 PHP 5 物件複製機制:從淺複製到深複製的完整解析

     編輯:PHP 相關知識

前言:為什麼需要「複製」物件?

PHP 5 採用 Zend Engine II,物件儲存於 Object Store,變數僅持有指標。當你寫 $tv2 = $tv1 時,兩個變數指向同一個實例。修改其中一個屬性,另一個也會跟著變——這不是複製,而是參考傳遞。要得到獨立副本,必須使用 clone 關鍵字。

基本複製:clone 關鍵字

class Television {
    protected $_color = 'black';
    public function getColor() { return $this->_color; }
    public function setColor($color) { $this->_color = (string)$color; return $this; }
}

$tv1 = new Television();
$tv2 = clone $tv1;           // 真正複製
$tv2->setColor('white');
echo $tv1->getColor(); // black(未受影響)
echo $tv2->getColor(); // white

__clone 魔術方法:複製後的客製化

當物件被 clone 時,會自動呼叫 __clone()。常見用途:重設唯一識別碼、重新建立關聯物件。

class Television {
    protected $_identity = 0;
    protected $_color = 'black';
    protected $_control = null;

    public function __construct() { $this->_control = new Telecontrol(); }
    public function getControl() { return $this->_control; }
    public function setIdentity($id) { $this->_identity = (int)$id; return $this; }
    public function getIdentity() { return $this->_identity; }

    public function __clone() {
        $this->setIdentity(0);                    // 重設編號
        $this->_control = new Telecontrol();      // 重新建立遙控器(關鍵!)
    }
}

class Telecontrol {}

淺複製的致命缺陷:關聯物件未複製

預設 clone 為淺複製:基本型別屬性複製值,但物件屬性仍指向同一個實例。上例若不在 __clone 中 new Telecontrol(),兩台電視會共用同一支遙控器,違反現實邏輯。

方案一:在 __clone 中手動重建關聯

優點:可控性高;缺點:類別屬性多、層級深時維護困難,且無法修改第三方類別。

方案二:序列化實現深複製

利用 serialize() + unserialize() 遞迴複製整個物件圖,包含所有巢狀物件。

$tv1 = new Television();
$tv2 = unserialize(serialize($tv1)); // 深複製

// 驗證
echo spl_object_id($tv1->getControl()); // 不同 ID
echo spl_object_id($tv2->getControl()); // 不同 ID

注意:此法不會觸發 __clone,但會觸發 __sleep/__wakeup。若需兩者兼顧,可深複製後再 clone 一次(效能略有影響)。

深複製的考量點

  • 遞迴深度:物件圖過深可能導致效能問題或記憶體耗盡。
  • 循環參考:A 參考 B,B 又參考 A,序列化會處理,但需測試。
  • 資源型別:資料庫連線、檔案控制代碼等資源無法序列化,需在 __sleep 排除、__wakeup 重建。

總結與建議

方式適用場景優點缺點
參考指派(=)需共享同一實例效能最好非獨立副本
clone(淺複製)無巢狀物件、或僅需複製基本屬性語法簡單、觸發 __clone關聯物件共享
__clone 手動重建關聯物件少、需客製化邏輯完全可控維護成本高
序列化深複製複雜物件圖、第三方類別、需完整隔離一次複製所有層級效能較差、資源型別需特殊處理

PHP 5 的物件模型與 Java 相似,可參考 Java 的 Cloneable、序列化、複製建構子等最佳實踐。實務上建議:優先考慮不可變物件設計,減少複製需求;必須複製時,根據物件複雜度選擇淺/深複製,並撰寫單元測試驗證獨立性。

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