2013-07-11 32 views
0

我正試圖在Symfony2中實現軟刪除功能。它主要是以我想要的方式工作,但是我在相關實體方面遇到了一些麻煩。對於非關鍵數據,我希望能夠軟刪除相關的實體,但仍保留所有數據。如何過濾實體關係以返回主對象,但不是相關的對象? (Symfony2/Doctrine2)

例如,假設我有一個帳戶實體與城市的實體,具有以下表結構:

table: account 
--------------------------- 
id | account_name | city_id 
--------------------------- 
1 | Jane Doe  | 1 
2 | John Smith | 1 
3 | Dave Jones | 2 


table: city 
--------------------------- 
id | city_name | deleted 
--------------------------- 
1 | Phoenix | 1 
2 | New York | 0 

因此,在這種情況下,「鳳凰」已經軟刪除,並在兩排帳戶表已保留該鏈接。通過這種方式,可以取消刪除Phoenix並且不會丟失數據。

很顯然,如果鳳凰已被軟刪除,我不想在查看帳戶時顯示該數據。我創建了一個Doctrine過濾器,它將過濾出行數爲deleted = 1。但是,由於Account表中的鏈接列仍然存在,因此它本質上指向一個不存在的相關對象(Phoenix),因此拋出了EntityNotFoundException。

這是我的問題。我怎樣才能在保留兩個對象之間的鏈接的同時顯示一個軟刪除城市的賬戶列表?

在我的腦海裏,查看帳戶列表時,它應該導致這樣的事情:

Account Name | City 
--------------------------- 
Jane Doe  | - 
John Smith | - 
Dave Jones | New York 

作爲一個快速實驗,我試着捕捉EntityNotFoundException,只是返回的數據呢。這似乎按照我的意圖工作,但這是一個相當醜陋的黑客攻擊,必須在整個地方重複(除非有另一種我不知道的方式)。下面是我測試過的SonataAdmin CRUDController的一個例子:

try { 
    return $this->render($this->admin->getTemplate('list'), array(
     'action' => 'list', 
     'form'  => $formView, 
     'datagrid' => $datagrid 
    )); 
} catch (\Twig_Error_Runtime $e) { 
    if (strpos($e->getMessage(), 'Entity was not found')) { 
     return $this->render($this->admin->getTemplate('list'), array(
      'action' => 'list', 
      'form'  => $formView, 
      'datagrid' => $datagrid 
     )); 
    } 
} 

我對這個解決方案並不舒服;我覺得我錯過了一個更好的方法。

根據記錄,這是我的過濾器:

class SoftDeleteFilter extends SQLFilter 
{ 
    public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) 
    { 
     if (!$targetEntity->hasField('deleted')) { 
      return ''; 
     } 

     return $targetTableAlias . '.deleted = false'; 
    } 
} 

提前感謝!

+0

我還沒有嘗試過,你要完成什麼,但我會建議你要考慮查詢應該是什麼樣子。在我看來,反對城市表的連接應該看起來像這樣:'LEFT JOIN city AS c ON c.id = someAlias.city_id AND c.deleted!= 1'。如果你能夠構建這種'leftJoin',那麼你應該能夠解決這個問題。 –

+0

我只是看看這些查詢,而且它已經是它的樣子了。 – scootstah

+0

您是否可以不使用管理環境中的SoftDeleteFilter? –

回答

0

這是Doctrine2的一個已知限制,它是reported a while ago

official recommendation遺憾的是不使用這種模式,而是管理刪除標誌業務​​邏輯,就像這樣:

class Employee 
{ 
    // ... 
    private $manager; // soft-deleted to-one association 
    public function getManager() 
    { 
     return $this->manager && $this->manager->active() ? $manager : null; 
    } 
} 

class Manager 
{ 
    // ... 
    private $deleted; // soft-delete flag, mapped as datetime|null 
    public function active() 
    { 
     return ! $this->deleted; 
    } 
}