gus*_*omr 4 php arrays crud doctrine-orm
有没有解决办法自动执行此操作?
我的两个实体:
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;
}
Run Code Online (Sandbox Code Playgroud)
存在两个产品已关联的ID(1,2)的用户实体:
$user = $entityManager->find('User', 1);
Run Code Online (Sandbox Code Playgroud)
此数组来自视图,其中包含要插入,删除或已在列表中的新产品数据不执行任何操作:
$array = array(1, 3, 4);
Run Code Online (Sandbox Code Playgroud)
在这种情况下:
1 = Already in association with User (do nothing)
2 = not in array and should be deleted
3 = should be inserted
4 = should be inserted
Run Code Online (Sandbox Code Playgroud)
如何在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();
Run Code Online (Sandbox Code Playgroud)
并setProducts定义为
function setProducts($products) {
$this->products = new ArrayCollection($products);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,doctrine将删除所有用户的产品关联,然后插入从视图传入的每个产品关联.
我在我的系统上对此进行了测试,其中visit实体与许多visit_tag实体相关联.请注意,doctrine会在下面的profiler截图中删除visit_tag给定visit对象的所有关联,然后创建每个关联.

为了让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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,探查器显示doctrine只删除特定关联(而不是全部),并且只插入新关联.

但是,为了执行手动合并原则,请查询所有关联的数据库,否则您不必这样做.简而言之:
方法1
方法2
当关联的#变化与关联的总数相比相对较小时,方法2更好.但是,如果您要更改大多数关联,方法1似乎是要走的路.