Doctrine + Symfony2: Forms:从包含在另一个集合中的集合中删除已删除的元素


Doctrine + Symfony2: Forms: Removing deleted element from a collection that is contained in another collection

我有一个包含一个集合的表单,其中包含另一个集合,两个集合都有allow_add &allow_delete设置为true。但是当从子集合中删除一些项目时,我遇到了一个问题。我遵循Symfony2文档,为了简单起见,我将使用来自http://symfony.com/doc/current/cookbook/form/form_collections.html

的相同文档示例。
class Task
{
    protected $description;
    protected $tags;
    ....
}

class Tag
{
    protected $name;
    protected $categories;
     ....
}

class Category
{
    protected $name;
    ....
}

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

$originalTags = new ArrayCollection();
// Create an ArrayCollection of the current Tag objects in the database
foreach ($task->getTags() as $tag) {
    $originalTags->add($tag);
} 

这里的Tags按值复制,而tags中的Categories仍然按引用复制,一旦用户从表单中删除一个,它也从$originalTags中删除。

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


<

附加信息/strong>

我试图实现__cloneTag像这样:

in Tag:

public function __clone()
{
    $this->categories = new ArrayCollection();
}

和i改变了$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
}

我们必须验证一些东西,然而,因为如果你clone一个"原则"对象,entity manager可能会"丢失"它的引用,并且无法再次将其持久化到db(当然,如果你需要的话)