2016-07-31 35 views
1

爲了解決一個problem I asked about earlier,我想創建一個自定義的庫函數,將確定的Repair一個實例是否是唯一的基礎上,devicenamecolors限制。學說:自定義庫,以確定UniqueEntity不起作用

這是我爲Repair類主義詮釋。請注意,device屬性是多對一(許多修復爲一個設備),並且colors是多對多。

/** 
* @ORM\Table(name="repair") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\RepairRepository") 
* @UniqueEntity(fields={"name", "device", "colors"}, repositoryMethod="getSimilarRepairs", message="Repair {{ value }} already exists for this name, device and colour combination.") 
*/ 

這是我的RepairRepository.php,其中$criteria['colors']是一個數組。

public function getSimilarRepairs(array $criteria) { 
    $builder = $this->createQueryBuilder('r') 
     ->where('r.device = :device') 
     ->andWhere('r.colors = :colors') 
     ->andWhere('r.name = :name') 
     ->setParameters(['deviceid'=>$criteria['device'],'colors'=>$criteria['colors'],'name'=>$criteria['name']]); 
    return $builder->getQuery(); 
} 

我有大概可以帶回一個三個問題:

  • 編輯:每變化,造成重複或不,我得到一個重複的實體存在的消息。
  • 編輯:儘管有錯誤消息,名稱更改仍然執行!
  • 添加:我可以創建儘可能多的重複項,因爲我喜歡,從來沒有錯誤消息。
+0

你是否看到這篇文章? http://stackoverflow.com/questions/16148678/symfony-2-uniqueentity-repositorymethod-fails-on-update-entity – DOZ

+0

Yous自定義查詢與默認查詢的作用相同。這是正常的,它不會工作:)我會試一試。 – Alsatian

回答

0

您的問題是色彩關係是多對多。 在SQL中,您無法在此關係上查詢'='。

這是非常複雜的,這就是爲什麼學說(我們可能)不能讓它孤單。

的部分解決方案構建查詢:

public function getSimilarRepairs(array $criteria) { 
    $builder = $this->createQueryBuilder('r') 
     ->where('r.device = :device') 
     ->andWhere('r.name = :name')->setParameter('name',$criteria['name']) 
     ->andWhere('r.colors = :colors')->setParameter('deviceid',$criteria['device']); 

    // r matches only if each of your colors exists are related to r : 
    $i=0; 
    foreach($criteria['colors'] as $color){ 
     $i++; 
     $builder->join('r.colors','c'.$i)->andWhere('c = :color'.$i)->setParameter('color'.$i,$color); 
    } 

    // Then you had also to check than there is no other color related to r : 

    // I don't know how 


    return $builder->getQuery(); 
} 

但讓我提出另一種解決方案:

在你的修爲實體,你可以存儲你的相關顏色的重複:

/** 
* @var string 
* 
* @ORM\Column(name="name_canonical", type="string") 
*/ 
private $serializedColors; 

使用原則生命週期事件設置它:

/** 
* @ORM\PrePersist 
* @ORM\PreUpdate 
*/ 
public function updateColors() 
{ 
    $serializedColors = ''; 

    foreach($this->colors as $color){ 
     $serializedColors .= $color->getId().'#'; 
    } 

    $this->serializedColors = $serializedColors; 
} 

不要忘記添加@HasLifecycleCallbacks

然後你UniqueEntityConstraint更改爲fields={"name", "device", "serializedColors"},忘記了自定義查詢,它會工作。

+0

這是一個非常有趣的解決方案@Alsatian。從來沒有這樣想過。但它確實感覺有點「骯髒」,爲了純粹的目的規避邏輯而保存數據,但我認爲它會提高性能。謝謝,我會稍微嘗試一下,並儘快回覆。 – bluppfisk

+0

Y這是骯髒的,但我從來沒有找到更好的這種用法。 – Alsatian