2013-02-11 68 views
6

我正在構建一個應用程序,用戶可以在其中編輯一些數據,然後顯示一個可以確認(並評論)其編輯的屏幕。Symfony 2/Doctrine 2:獲取對PersistentCollection的更改

在確認表單中,我顯示對實體所做的更改。這適用於「正常」字段。下面是一些代碼,用於檢查單場工程:

// create $form 
// bind $form 

if ($form->isValid() { 
    $data = $form->getData(); 
    // example, get changes of a "normal" field 
    if ($data['color'] != $entity->getColor()) { 
     // do something with changes 
    } 
} 

但我不能做同樣的關係(與用戶例如多對多):

if ($data['users'] != $entity->getUsers() 

不會因爲$工作data ['users']和$ entity-> getUsers()引用相同的持久集合。可以調用此函數來查看是否有變化:

if ($data['users']->isDirty()) 

但是不可能看到做了哪些更改。

上面的第二個問題是,如果從持久集合中刪除所有項目,Doctrine不會將其標記爲「已更改」(isDirty()= true),所以我無法捕捉到具體更改用戶從表單中的實體中刪除所有「用戶」。

請注意,代碼全部有效,唯一的問題是我無法查看/處理在確認步驟中所做的更改。

+0

檢索$ entity-> getUsers()之前綁定?同時檢查並查看您的表單類型是否通過引用添加字段。 – Lighthart 2013-02-12 07:39:31

+0

@Lighthart這是一個好主意(參考)!將檢查並取回給你... – mogoman 2013-02-13 11:18:11

+0

@Lighthart不起作用,因爲引用是針對集合的,而不是針對實體的字段 – mogoman 2013-02-14 20:50:35

回答

0

在綁定之前將原始集合存儲在變量中,然後比較綁定後的新集合。 PHP有很多數組比較函數,並且通過$ collection-> toArray()可以將集合轉換爲本地數組。

如:

// create form 
$oldusers=$entity->getUsers()->toArray(); 
// bind form 
if ($form->isValid() { 
    $data = $form->getData(); 
    if ($data['users'] != $oldusers) { 
     // do something with changes 
    } 
} 
+0

不起作用,之後綁定$ oldusers也得到更新與更改。這是因爲$ oldusers引用了相同的集合。 – mogoman 2013-02-15 08:07:45

+0

上面編輯。只需將其轉換爲數組即可。 _no_方式是一個數組,一個對象可以是同一個內存位置。 – Lighthart 2013-02-15 15:30:03

+0

謝謝。結束使用toArray()。如果有人想評論/改進它,我也會添加我的最終解決方案。 – mogoman 2013-02-15 17:31:58

6

Doctrine\ORM\PersistentCollection具有能夠在Doctrine\ORM\UnitOfWork的生命週期事件中使用的內部API(公共)方法getSnapshotgetDeleteDiffgetInsertDiff。例如,您可以在onFlush期間檢查持久集合的插入比較。

+0

,謝謝+1,但如果整個集合已被擦除,則這些方法不起作用(isDirty()也是來自PersistentCollection的方法),這是我的主要問題。 – mogoman 2013-02-14 20:44:45

+0

在計算變更集(flush期間)後,您應該使用這些方法 – Ocramius 2013-02-15 08:33:28

+0

問題是我需要顯示用戶接受/取消的更改,這意味着我無法調用Flush() – mogoman 2013-02-15 17:19:17

3

解決這樣的:

1)獲取將直接向實體的變化,使用以下命令:

// create form 
// bind form 
// form isValid() 

$uow = $em->getUnitOfWork(); 
$uow->computeChangeSets(); 
$changeset = $uow->getEntityChangeSet($entity); 
print_r($changeset); 

2A)要得到關係的變化,使用上面的Lighthart的答案:

$oldUsers = $entity->getUsers()->toArray(); 
// bind form 
// form isValid 
$newUsers = $entity->getUsers()->toArray(); 
// compare $oldUsers and $newUsers 

2b)中使用關於持久性收集方法來查找插入/刪除:

$newUsers = $entity->getUsers(); 
$inserted = $newUsers->getDeleteDiff(); 
$deleted = $newUsers->getInsertDiff(); 

與唯一的問題(2b)的是,如果被去除的所有用戶和未加然後getDeleteDiff()是空的,其似乎是一個學說的bug/idiosyncrasy

+0

我正在摔跤這個,想知道在哪裏把這個邏輯。我的第一個想法是控制器行動,但每個人都說保持你的控制器瘦。我想我正在尋找一個事件監聽器 - 無論是在Doctrine事件系統還是Zend Framework 2的事件系統 - 我都可以在這裏找到它。當某些事情發生在實體的關聯中時,我需要清除緩存。 – David 2016-06-16 18:40:56

+0

先生,其輝煌的先生! – 2016-10-05 05:38:56

+0

我在2b中沒遇到過你的問題,getDeleteDiff()返回數組,即使所有的收集項都被刪除了。 – 2016-10-05 16:19:36