考虑下面的代码
$user = $entityManager->find('User', 1);
$products = array();
foreach(array(1, 3, 4) as $product_id) {
$products[$product_id] = $entityManager->getReference('MyBundle\Entity\Product', $product_id);
}
$user->setProducts($products);
$entityManager->persist($user);
$entityManager->flush();
And setProducts
定义为
function setProducts($products) {
$this->products = new ArrayCollection($products);
}
在这种情况下,原则将删除所有用户的产品关联,然后插入从视图传入的每个产品关联。
我在我的系统上测试了这个visit
实体与许多相关联visit_tag
实体。请注意,教义删除了所有visit_tag
给定的关联visit
下面的探查器屏幕截图中的对象,然后创建每个对象。
为了使学说仅根据需要删除/插入关联,您必须手动合并现有的$user->products ArrayCollection
而不是像上面那样覆盖它。您可以使用以下方法有效地做到这一点索引关联 http://doctrine-orm.readthedocs.org/en/latest/tutorials/working-with-indexed-associations.html通过indexBy
注释,它允许您在恒定时间内通过唯一键(即产品 ID)搜索/添加/删除关联。
class User
{
/**
* @ManyToMany(targetEntity="Product", inversedBy="users", indexBy="id")
* @JoinTable(name="user_product",
* joinColumns={@JoinColumn(name="user_id", referencedColumnName="idUser")},
* inverseJoinColumns={@JoinColumn(name="product_id", referencedColumnName="idProduct")}
* )
*/
protected $products;
public function setProducts($products) {
foreach($this->products as $id => $product) {
if(!isset($products[$id])) {
//remove from old because it doesn't exist in new
$this->products->remove($id);
}
else {
//the product already exists do not overwrite
unset($products[$id]);
}
}
//add products that exist in new but not in old
foreach($products as $id => $product) {
$this->products[$id] = $product;
}
}
}
现在,探查器显示该学说仅删除特定关联(而不是全部)并且仅插入新关联。
但是,为了执行手动合并原则,请查询数据库中的所有关联,否则您不必这样做。简而言之:
Method 1
- 删除所有关联
- 插入从视图传入的所有关联
Method 2
- 选择所有协会
- 仅删除那些不再存在的关联
- 仅插入视图中以前不存在的关联
当更改的关联数与关联总数相比相对较小时,方法 2 更好。然而,如果您要改变大部分关联,方法 1 似乎是最佳选择。