2014-09-27 69 views
9

我是Symfony和Doctrine的新手。Symfony2/Doctrine2 - ManyToOne - 保存反面

我有一個實體「用戶」和一個實體「類型」。一個用戶可以擁有一個喜歡的類型,一個類型可以擁有許多具有該喜好的特定類型的用戶。所以我需要一個(用戶)到一個(類型)的關係。

我實現了它,它工作正常(主要)。但有一件事我不明白。

如果我這樣做,它的工作原理:

$user = new User(); 
$type = new Type(); 

$user->setFavoriteType($type); 
$em->persist($user); 
$em->persist($type); 
$em->flush(); 

的對象生成並存儲到數據庫。而favorite_type_id設置正確。 所以更改擁有方按預期工作

但是,如果我將用戶添加到反面(僅)並刷新實體管理器,則不會設置favorite_type_id。

$user = new User(); 
$type = new Type(); 

$type->getUsers()->add($user); //same with $type->addUser($user); 
$em->persist($user); 
$em->persist($type); 
$em->flush(); 

這是爲什麼?有沒有理由不從反面工作?我真的必須手動設置嗎?如果我在像「$ user-> setFavoriteType($ this)」這樣的類型實體中操作addUser方法,它就會起作用。但是,這不應該成爲學說的任務嗎?

文檔說

當雙向關聯關係被更新,僅學說雙方對這些變化的一個檢查。這被稱爲該協會的擁有方。

所以它似乎是想要的行爲,是嗎?但爲什麼?由於性能?語義原因?

如果有人能向我解釋或告訴我我做錯了什麼,我會很高興。

+0

有趣的問題,我也很好奇這個邏輯背後的選擇。 – DonCallisto 2014-09-27 08:13:52

+0

http://doctrine-orm.readthedocs.org/en/latest/reference/unitofwork-associations.html – DonCallisto 2014-09-27 08:15:48

+0

你能告訴我們相關的實體嗎? – ReynierPM 2014-09-27 23:07:40

回答

3

查看Doctrine documentation on cascading.。通過添加cascade={"persist"}並清除緩存(重新構建Doctrine的元數據緩存),這應該可以幫助您快速輕鬆地開始看起來像是想要做的事情。

0

這是因爲從根本上講,當考慮持久性時,Doctrine將PHP實體直接映射到數據庫表。在您的情況下,用戶和類型在概念上具有多對一關係,但在數據庫級別,關係完全在用戶表中表示 - 用戶擁有最喜歡的類型,因此用戶表具有favorite_type_id列。儘管我們可以想到類型實體具有他們最喜歡的用戶列表,但實質上這也是通過查看用戶表獲得的,但Type表中沒有任何內容。

在Doctrine中設置實體映射告訴Doctrine實體之間的關係是什麼,並允許Doctrine爲您提供某些方便的訪問方法,如$type->getUsers(),但不會更改底層數據的存儲方式。如果我使用$user->setFavoriteType,我正在操作的數據有直接的數據庫通信,但是,默認情況下,如果我撥打$type->addUser,我不是 - 使這種呼叫立即可用的主要目的是保持您只需將物體丟棄並從數據庫中再次取回物體,即可與當前最新的水化物體進行合作。

當然,您已經看到您可以自定義addUser也可以調用setFavoriteType,或者按照Shon M的建議配置級聯持久性,以使行爲更像您期望/想要的那樣。看起來好像是浪費時間從一開始就放棄這一點,但我懷疑Doctrine開發者已經有意識地選擇以最簡單的方式實現所需的功能,而documenting it clearly並提供了幾個簡單的替代方案,如果這就是你以後,從而迎合每個人的方式或其他。無論喜不喜歡,數據庫中的數據以及PHP後期運行的數據在技術上都是不同的東西,尤其是像Doctrine這樣的模型,其中DB活動被推遲到開發人員請求它時,這會非常有意義儘可能明確地做出一切!