This is a very very simple behavior, but I can't find the way to achieve it with doctrine. I'm going to explain it reducing the complexity with only two entities.
Having two entites (Author and Book) related like "One Author owns zero or more books" and "One book is owned by zero or one author", I'm trying to unset the relation between an author and one of his books (from the author side), expecting that book.author_id field in database sets as null.
The Entities are defined as follow:
Author
/**
* Author
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Poc\PocBundle\Entity\AuthorRepository")
*/
class Author
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Author
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @ORM\OneToMany(targetEntity="Book", mappedBy="author", cascade={"persist", "remove"})
*/
private $books;
public function __construct()
{
$this->products = new ArrayCollection();
}
/**
* Add books
*
* @param \Poc\PocBundle\Entity\Book $books
* @return Author
*/
public function addBook(\Poc\PocBundle\Entity\Book $books)
{
$this->books[] = $books;
return $this;
}
/**
* Remove books
*
* @param \Poc\PocBundle\Entity\Book $books
*/
public function removeBook(\Poc\PocBundle\Entity\Book $books)
{
$this->books->removeElement($books);
}
/**
* Get books
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getBooks()
{
return $this->books;
}
}
Book
/**
* Book
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Poc\PocBundle\Entity\BookRepository")
*/
class Book
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Book
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @ORM\ManyToOne(targetEntity="Author", inversedBy="books")
* @ORM\JoinColumn(name="author_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $author;
/**
* Set author
*
* @param \Poc\PocBundle\Entity\Author $author
* @return Book
*/
public function setAuthor(\Poc\PocBundle\Entity\Author $author = null)
{
$this->author = $author;
return $this;
}
/**
* Get author
*
* @return \Poc\PocBundle\Entity\Author
*/
public function getAuthor()
{
return $this->author;
}
}
In the main controller I do the following.
Retrieve an author
Retrieve a Book owned by this author
Remove book from author
Persist Author & flush
Retrieve Book
Get the author ...
And the Author remains being the same. In database the field book.author_id of this record is not set to NULL as expected, but is still related with the author.
The Controller Code:
$Book = $this->getDoctrine()
->getRepository('PocPocBundle:Book')
->find('1');
$Author = $this->getDoctrine()
->getRepository('PocPocBundle:Author')
->find('1');
$Author->removeBook($Book);
$em = $this->getDoctrine()->getManager();
$em->persist($Author);
$em->flush();
echo "<pre>";
$Book = $this->getDoctrine()
->getRepository('PocPocBundle:Book')
->find('1');
\Doctrine\Common\Util\Debug::dump($Book);
die;
... And the output
object(stdClass)[286]
public '__CLASS__' => string 'Poc\PocBundle\Entity\Book' (length=25)
public 'id' => int 1
public 'name' => string 'El Quijote' (length=10)
public 'author' =>
object(stdClass)[293]
public '__CLASS__' => string 'Poc\PocBundle\Entity\Author' (length=27)
public '__IS_PROXY__' => boolean true
public '__PROXY_INITIALIZED__' => boolean true
public 'id' => int 1
public 'name' => string 'Cervantes' (length=9)
public 'books' => string 'Array(1)' (length=8)
In the output of entity Book (id=1) we can see this books is still related with the author.
Sure, I'm missing something but I can't find where is the gap.
If you want to remove the association between the Author and the Book entities, you should delete the association in your Book entity and persist it too by using $em->flush(). $em->persist($entity) is not used for entity removal. Deleting the association in your PHP objects and flush them through the ORM remove the association in the database.
Just check this in the Doctrine's documentation:
http://docs.doctrine-project.org/en/latest/reference/working-with-associations.html#removing-associations
I hope it will work for you. Cheers!