簡體   English   中英

如何建立學說聯系?

[英]How to set doctrine associations?

我知道實體中的關聯屬性是實現\\Doctrine\\Common\\Collections\\Collection 我知道在構造函數中應初始化此類屬性:

$this->collection = new \\Doctrine\\Common\\Collections\\ArrayCollection()

我知道我可以使用ArrayCollection#add()ArrayCollection#remove()修改集合。 但是我有不同的情況。

假設我有一個新的關聯實體簡單數組。 使用現有方法,我需要檢查數組中的每個元素:實體集合是否具有它。 如果否-將數組元素添加到實體集合。 除此之外,我需要檢查實體集合中的每個元素。 如果新數組中沒有任何集合元素,那么我需要將其從集合中刪除。 要做很多瑣碎的事情。

我想要的是? 要實現setProducts方法:

class Entity {
  private $products;

  // ... constructor

  public function setProducts(array $products)
  {
    // synchronize $products with $this->products
  }
}

我試過了: $this->products = new ArrayCollection($products) 但是,這會使主義刪除所有產品,並從$products參數中添加這些$products 我想要類似的結果,但沒有數據庫查詢。

在這種情況下,Doctrine中是否有任何內置解決方案?

編輯 :我想在ArrayCollection有一個方法,例如fromArray ,它將合並不需要的集合中的元素。 只需手動使用集合參數中的每個元素的add/remove調用進行復制。

原則集合沒有“合並”功能,該功能將從另一個集合中的數組或集合中添加/刪除實體。

如果要“簡化”使用添加/刪除描述的手動合並過程,則可以使用array_merge假設兩個數組都不是數字的,而是具有某種唯一鍵,例如實體的spl_object_hash

public function setProducts(array $products)
{
    $this->products = new ArrayCollection(
        array_merge(
            array_combine(
                array_map('spl_object_hash', $this->products->toArray()),
                $this->products->toArray()
            ),
            array_combine(
                array_map('spl_object_hash', $products),
                $products->toArray()
            )
        )
    );
}

您可能要使用產品ID而不是spl_object_hash作為具有相同ID的2個產品,但是創建為單獨的實體-例如,通過findBy()和使用new Product()手動創建的一個-將被識別為2個不同的產品並可能導致另一個插入嘗試。

但是,由於用新的ArrayCollection替換了保存先前獲取的產品的原始PersistentCollection,因此在刷新EntityManager時,這仍可能導致不必要的查詢或產生意外結果。 更不用說,與在原始Collection上顯式調用addElement / removeElement相比,此方法可能更難閱讀。

我將通過創建自己的擴展了Doctrine數組集合類的集合類來解決這個問題:

use Doctrine\Common\Collections\ArrayCollection;

class ProductCollection extends ArrayCollection
{
}

在實體本身中,您可以在__constructor初始化它:

public function __construct()
{
    $this->products = new ProductCollection();
}

在這里,Doctrine您將使用您的集合類獲取產品結果。 之后,您可以添加自己的函數來處理特殊的合並,也許是這樣:

public function mergeProducts(ProductCollection $products): ProductCollection
{
    $result = new ProductCollection();
    foreach($products as $product) {
        $add = true;
        foreach($this->getIterator() as $p) {
            if($product->getId() === $p->getId()) {
                $result->add($product);
                $add = false;
            }
        }
        if($add) {
            $result->add($product);
        }
    }
    return $result;
}

它將返回一個全新的產品集合,您可以替換實體中的其他集合。 但是,如果該實體是附加的並且受原則控制,則它將在另一端呈現SQL,如果您想在不冒着數據庫更新風險的情況下使用該實體,則需要分離該實體:

$entityManager->detach($productEntity);

希望這會有所幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM