[英]How to load all associations for a result set in a single query in Doctrine2
[英]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.