Доктрина 2, как удалить много-много ассоциаций? - PullRequest
8 голосов
/ 04 сентября 2011

Как удалить связь из таблицы «многие ко многим», не удаляя ничего?

Я пробовал:

$getProject = $this->_helper->getDocRepo('Entities\Project')->findOneBy(array('id' => $projectId));
$getCat = $this->_doctrine->getReference('\Entities\Projectcat', $catId);

$getProject->getCategory()->removeElement($getCat);
$this->em->flush();

мой объект Projectcat:

/**
 * @ManyToMany(targetEntity="\Entities\Projectcat", cascade={"persist", "remove"})
 * @JoinColumn(name="id", referencedColumnName="id")
 */
protected $getCategory;

Ответы [ 3 ]

9 голосов
/ 28 января 2015

Довольно старая запись, но она хотела предоставить способ гарантировать, что связь была удалена со стороны сущности ORM в доктрине, вместо того, чтобы вручную выполнять коллекцию removeElement каждой сущности и расширять ответ @Rene Terstegen.

Проблема в том, что Doctrine не «автоматически» связывает ассоциации, однако вы можете обновить методы Add / Remove объекта для этого.

https://gist.github.com/Ocramius/3121916

Приведенный ниже пример основан на схеме проекта / категории ОП. Предполагается, что таблица project_category является таблицей отношений ManyToMany, а таблицы project и category используют первичный ключ id.

class Project
{

    /**
     * @ORM\ManyToMany(targetEntity="Category", inversedBy="projects")
     * @ORM\JoinTable(
     *  name="project_category",
     *  joinColumns={
     *      @ORM\JoinColumn(name="project", referencedColumnName="id")
     *  },
     *  inverseJoinColumns={
     *      @ORM\JoinColumn(name="category", referencedColumnName="id")
     *  }
     * )
     */
    protected $categories;

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

    /**
     * @param Category $category
     */
    public function removeCategory(Category $category)
    {
        if (!$this->categories->contains($category)) {
            return;
        }    
        $this->categories->removeElement($category);
        $category->removeProject($this);
    }
}

class Category
{    
    /**
     * @ORM\ManyToMany(targetEntity="Project", mappedBy="categories")
     */
    protected $projects;

    public function __construct()
    {
        $this->projects = new ArrayCollection();
    }

    /**
     * @param Project $project
     */
    public function removeProject(Project $project)
    {
        if (!$this->projects->contains($project)) {
            return;
        }    
        $this->projects->removeElement($project);
        $project->removeCategory($this);
    }
}

Тогда все, что вам нужно сделать, это вызвать метод removeCategory или removeProject вместо обоих. То же самое можно применить к методам addCategory и addProject.

$project = $em->find('Entities\Project', $projectId);
$category = $em->getReference('Entities\Category', $categoryId);
$project->removeCategory($category);
$em->flush();
9 голосов
/ 28 октября 2011

Ваша информация немного ограничена. Некоторая дополнительная информация о схеме базы данных и Project была бы хорошей. Но чтобы попробовать.

Вы должны удалить его с обеих сторон отношений. Вы удалили его из категории, но вы также должны удалить его из проекта.

// Remove Category from Project
$Project->Category->removeElement($Category);
// Remove Project from Category
$Category->Project->removeElement($Project);

Удачи!

0 голосов
/ 11 сентября 2012

Старый пост, но ответ выше помог мне, но он может помочь немного расширить его, у меня есть проект, который может иметь много категорий (и категорий, которые могут иметь много проектов), поэтому этот код дает мне все из них:

$project->getCategories();

Если я хочу удалить все категории для проекта, я просто делаю это:

 foreach ($project->getCategories() as $category) {
    $project->getCategories()->removeElement($category);
 }

Проблема с первоначальным вопросом заключалась в том, что, как мне кажется, Doctrine хочет, чтобы вы указали категорию, на которую ссылается проект, а не просто ссылку на категорию, которую вы захватили независимо с помощью этого кода:

$getCat = $this->_doctrine->getReference('\Entities\Projectcat', $catId);

Надеюсь, это имеет смысл. Я знаю, что немного испортил терминологию.

...