Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

doctrine 2, how to remove many to many associations?

How do you unlink a relation from a many-to-many table without deleting anything?

I have tried:

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

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

my Projectcat entity:

/**
 * @ManyToMany(targetEntity="\Entities\Projectcat", cascade={"persist", "remove"})
 * @JoinColumn(name="id", referencedColumnName="id")
 */
protected $getCategory;
like image 685
dean jase Avatar asked Sep 04 '11 13:09

dean jase


2 Answers

A rather old post but wanted to provide a way to ensure the association was removed from the ORM Entity side of doctrine, rather than of having to manually execute each Entity's collection removeElement and to expand on the answer by @Rene Terstegen.

The issue is that Doctrine does not "auto-magically" tie together the associations, you can however update the entity's Add/Remove methods to do so.

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

The below example is based on the OP's project/category schema. It assumes that the table project_category is the ManyToMany relationship table, and the project and category tables use the primary key 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);
    }
}

Then all you need to do is to call the removeCategory or removeProject method, instead of both. The same can be applied for addCategory and addProject methods as well.

$project = $em->find('Entities\Project', $projectId);
$category = $em->getReference('Entities\Category', $categoryId);
$project->removeCategory($category);
$em->flush();
like image 178
Will B. Avatar answered Oct 20 '22 07:10

Will B.


Your information is a bit limited. Some extra information about the database scheme and Project would be nice. But to give it a try.

You have to remove it from both sides of the relationship. You removed it from the category, but you should also remove it from the project.

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

Good luck!

like image 25
Rene Terstegen Avatar answered Oct 20 '22 07:10

Rene Terstegen