2013-05-21 28 views
2

文檔發出警告確保在原則2個實體喚醒和克隆實現了幾聲,如:爲什麼在教義2中需要安全的喚醒和克隆方法?

http://docs.doctrine-project.org/en/latest/cookbook/implementing-wakeup-or-clone.html

它沒有說爲什麼,但是......我相信它是與不與Doctrine的實體管理器以及它可能維護的內存緩存混雜在一起,但是粗略地深入(巨大的)代碼庫並沒有多說,也沒有對用戶列表進行快速搜索。

任何熟悉教義內部構件的人都知道,爲什麼教義2需要在實體上安全地喚醒和克隆方法?

回答

6

Doctrine 2需要將從數據庫中提取的數據轉換爲實體(php對象)。這個過程被稱爲水合。

原則2不使用使用new運營商(從而構建了一類)的傳統方法,但它使用下面的方法:

  • 它建立代表的序列化空版本的字符串你類。
  • 它將該字符串反序列化以使其成爲實際對象。這就是爲什麼你需要安全地執行__wakeup
  • 它將該對象存儲爲原型。

該過程對每個實體類都執行一次。

然後,只要需要水合一個實體,它就會克隆原型。這就是爲什麼您需要安全地實施__clone

這是全部完成的一個小方法newInstance()ClassMetadataInfo

這樣做的好處是,當一個新的實體水合時,不使用構造函數。這使開發人員可以在構造函數中自由地做任何他/她想要的事情(包括使用參數)。

更新

爲什麼你需要安全地實現__wakeup__clone方法的原因是這樣的:

因爲教義2 unserializes和克隆實體時,它需要滋潤他們,這些方法將被調用。但是當第2條原則做到這一點時,實體將會有而不是有任何數據集(甚至沒有標識符)。數據將在之後設置。當你實現它們以這樣的方式,當實體確實有標識符(S)你的邏輯只能進行

所以,你確信你的邏輯時,才執行時反序列化或克隆的實體,而不是當第二條原則。

+0

我已經添加了後續的答案突出主義的理由這樣做了。 –

2

賈斯珀的答案指出了確切的原因,但它沒有給出背景 - 正如爲什麼原則正在進行反序列化和克隆實體。

合理這樣做是允許的實體來定義他們想要的任何構造,如本博客文章解釋說:

http://www.doctrine-project.org/2010/03/21/doctrine-2-give-me-my-constructor-back.html

2010 ConFoo我的演示過程中,有人問起構造第2條原則中的實體以及它是否可以使用。我認爲這是值得寫的東西,因爲在第一條學說中這是不可能的。這個構造函數從你那裏受到歡迎,並在Doctrine內部使用。

在Doctrine 2中,可以在實體類中定義構造函數,並且不要求它是一個零參數構造函數!沒錯,Doctrine 2從來沒有實例化實體的構造函數,所以你完全可以控制!

這可能是由於其他兩個項目php-object-freezer和Flow3使用的小技巧。它的要點是我們存儲一個原型類實例,該類實例從手工製作的序列化字符串中解序列化,其中類名稱連接到字符串中。當我們反序列化字符串時的結果是該類的一個實例,它被存儲爲一個原型,並在每次我們需要一個新的實例進行水合時克隆。

有專人負責這個一看方法:

<?php 
public function newInstance() 
{ 
    if ($this->_prototype === null) { 
     $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); 
    } 
    return clone $this->_prototype; 
} 
相關問題