Php 条令+;Symfony2:窗体:从包含在另一个集合中的集合中删除已删除的元素

Php 条令+;Symfony2:窗体:从包含在另一个集合中的集合中删除已删除的元素,php,symfony,doctrine-orm,Php,Symfony,Doctrine Orm,因此,我有一个包含一个集合的表单,其中包含另一个集合,两个集合都将allow\u add和allow\u delete设置为true。但是我在从子集合中删除某些项目时遇到了一个问题。我遵循Symfony2文档,为了简单起见,我将使用来自的相同文档示例 现在,在用户更新表单之后,我必须通过比较原始集合和新集合来确保数据库的持久性。从Symfony2文档: $originalTags = new ArrayCollection(); // Create an ArrayCollection of t

因此,我有一个包含一个集合的表单,其中包含另一个集合,两个集合都将
allow\u add
allow\u delete
设置为
true
。但是我在从子集合中删除某些项目时遇到了一个问题。我遵循Symfony2文档,为了简单起见,我将使用来自的相同文档示例

现在,在用户更新表单之后,我必须通过比较原始集合和新集合来确保数据库的持久性。从Symfony2文档:

$originalTags = new ArrayCollection();
// Create an ArrayCollection of the current Tag objects in the database
foreach ($task->getTags() as $tag) {
    $originalTags->add($tag);
} 
这里,
标记
按值复制,而
标记
中的
类别
仍按引用复制,并且一旦用户从表单中删除一个,它也从
$originalTags
中删除

我解决了这个问题,但它变得相当复杂,我确信这种方法不是最好的,所以我正在寻找更好的方法


其他信息

我试图在类
标记上实现
\u clone
,如下所示:

标记中

public function __clone()
{
    $this->categories = new ArrayCollection();
}
我将
$originalTags
的创建方式更改为:

$originalTags = new ArrayCollection();
foreach ($task->getTags() as $tag) {
    $cat_array = array();
    $t = clone $tag;

    foreach($tag->getCategories() as $category) {
      $t->addCategory(clone $category);
    }
    $originalTags->add($t);
}
这就是我计算变更集并保存实体的方式:

foreach ($originalTags as $tag) {
     if (false === $task->getTags()->exists(function ($key, $element) use ($tag) {if($element->getId() == $tag->getId() )return true;  })) {
         $temp = $entityManager->find('...\Tag', $tag->getId());
         $entityManager->remove($temp);
         } else {
            foreach($task->getTags() as $t)
            {
               if($t->getId() == $tag->getId())
               {
                   $originalTag = $t;
               }
            }
            foreach ($tag->getCategories() as $category) {
               if (false === $originalTag->getCategories()->exists(function ($key, $element) use ($category) {if($element->getId() == $category->getId() )return true;})) {
                   $temp = $entityManager->find('...\Category', $category->getId());
                   $entityManager->remove($temp);
               }
            }
        }
     }
 }

你为什么不试试像这样的东西

$originalTags = new ArrayCollection();
// Create an ArrayCollection of the current Tag objects in the database
foreach ($task->getTags() as $tag) {
    $cat_array = array();
    foreach($tag->getCategories() as $categories) {
       $cat_array[] = clone $categories;
    }
    $originalTags->addCategories($cat_array); //you have to write this method
}

但是,我们必须验证一些东西,因为如果您克隆了一个“条令”对象,
实体管理器可能会“丢失”其引用,并且无法将其再次保存到db(当然,如果您需要的话)

正在尝试类似的操作。似乎一旦克隆对象并比较原始对象和新的
$category
失败,
$tag->getCategories()->contains($category)
将始终返回false。当然,它将失败;它们不是同一个物体。。。我的意思是,你可以覆盖
->contains()
操作,只比较实体id(或者主键,如果你愿意)并执行这个技巧,但是假设我克隆了一个
类别
,那么条令就不能再管理它了,之后,用户删除该类别,这样它就不再存在于
$tag->getCategories()中
因此,一旦我在原始类别和新类别之间进行比较,我会发现缺少的类别,因此我需要将其删除,但我无法将其从原始数组中删除,因为它是克隆的,也无法从其自身的对象中删除,因为它已被表单删除class@ra_htial:是的,我明白你的意思,但目前我帮不了你更多:(不用担心,非常感谢!
$originalTags = new ArrayCollection();
// Create an ArrayCollection of the current Tag objects in the database
foreach ($task->getTags() as $tag) {
    $cat_array = array();
    foreach($tag->getCategories() as $categories) {
       $cat_array[] = clone $categories;
    }
    $originalTags->addCategories($cat_array); //you have to write this method
}