繁体   English   中英

更新多对多关联学说2

[英]Update many-to-many association doctrine2

有没有解决办法自动执行此操作?

我的两个实体:

class User
{
    /* *
    * @ManyToMany(targetEntity="Product", inversedBy="users")
    * @JoinTable(name="user_product",
    *  joinColumns={@JoinColumn(name="user_id", referencedColumnName="idUser")},
    * inverseJoinColumns={@JoinColumn(name="product_id", referencedColumnName="idProduct")}
    * 
    * )
    */
protected $products;
}

class Product {
    /**
    * @ManyToMany(targetEntity="User", mappedBy="products")
    */
protected $users;
}

用户实体有两个产品已经相关ID存在( 12 ):

$user = $entityManager->find('User', 1);

此数组来自视图,其中包含要插入,删除或已在列表中的新产品数据不执行任何操作:

$array = array(1, 3, 4);

在这种情况下:

1 = Already in association with User (do nothing)
2 = not in array and should be deleted
3 = should be inserted
4 = should be inserted

如何在doctrine2中做到这一点? 是否有合并功能自动执行或shoud我手动执行?

请考虑以下代码

$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();

并将setProducts定义为

function setProducts($products) {
  $this->products = new ArrayCollection($products);
}

在这种情况下,doctrine将删除所有用户的产品关联,然后插入从视图传入的每个产品关联。

我在我的系统上对此进行了测试,其中visit实体与许多visit_tag实体相关联。 请注意,doctrine会在下面的profiler屏幕截图中删除给定visit对象的所有visit_tag关联,然后创建每个。

在此输入图像描述

为了使doctrine只根据需要删除/插入关联,您必须手动合并现有的$user->products ArrayCollection而不是像上面那样覆盖它。 并且您可以通过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;
        }    
    }
}

现在,探查器显示doctrine只删除特定关联(而不是全部),并且只插入新关联。

在此输入图像描述

但是,为了执行手动合并原则,请查询所有关联的数据库,否则您不必这样做。 简而言之:

方法1

  1. 删除所有关联
  2. 插入从视图传入的所有关联

方法2

  1. 选择所有关联
  2. 仅删除那些不再存在的关联
  3. 仅插入之前不存在的视图中的那些关联

当关联的#变化与关联的总数相比相对较小时,方法2更好。 但是,如果您要更改大多数关联,方法1似乎是要走的路。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM