ramsey_lewis
ramsey_lewis

Reputation: 598

doctrine : onDelete="CASCADE" not working correctly?

I have 2 entity with a manyToMany relationship : Teacher and Subject.

Can you tell me why i've got empty row ? I want to delete these Subject with no Teacher attached.

Edit

I added cascade={"remove", "persist"}, on Teacher (see my entities below), but now, if i have this :

|Subject name|Teacher(s)|
 ------------------------
|Maths       | John, Bob, Bill|
|Science     | John     |
|Sport       | Doe      |
|Foo         | Bar      |
|Babar       | John     |

Teacher(s) |
------------
| John     |
| Doe      |
| Bar      |
| ...      |

i get that when i delete John :

|Subject name|Teacher(s)|
 ------------------------  Not good
|                       | <-- entire row deleted
|Science     | John     |
|Sport       | Doe      |
|Foo         | Bar      |
|            |          | <-- here too

Teacher(s) |
------------
| John     |
| Doe      |
| Bar      |
| ...      |

instead of this :

|Subject name|Teacher(s)|
 ------------------------  Good
|Maths       | Bob, Bill|  <-- only jhon deleted
|Science     | John     |
|Sport       | Doe      |
|Foo         | Bar      |
|            |          | <-- entire row deleted

Teacher(s) |
------------
| Doe      |
| Bar      |
| ...      |

I want to delete the Subject row only if there is not Teacher attached

Here my entities

Teacher :

class Teacher
{
/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="firstname", type="string",     length=255)
 */
private $firstname;

/**
 * @var string
 *
 * @ORM\Column(name="lastname", type="string", length=255)
 */
private $lastname;

/**
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Subject", cascade={"remove", "persist"}, mappedBy="teachers"))
 */
private $subjects;


/**
 * Get id
 *
 * @return integer
 */
public function getId()
{
    return $this->id;
}

/**
 * Set firstname
 *
 * @param string $firstname
 *
 * @return Teacher
 */
public function setFirstname($firstname)
{
    $this->firstname = $firstname;

    return $this;
}

/**
 * Get firstname
 *
 * @return string
 */
public function getFirstname()
{
    return $this->firstname;
}

/**
 * Set lastname
 *
 * @param string $lastname
 *
 * @return Teacher
 */
public function setLastname($lastname)
{
    $this->lastname = $lastname;

    return $this;
}

/**
 * Get lastname
 *
 * @return string
 */
public function getLastname()
{
    return $this->lastname;
}

/**
 * Constructor
 */
public function __construct()
{
    $this->subjects = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add subject
 *
 * @param \AppBundle\Entity\Subject $subject
 *
 * @return Teacher
 */
public function addSubject(\AppBundle\Entity\Subject $subject)
{
    $this->subjects[] = $subject;

    return $this;
}

/**
 * Remove subject
 *
 * @param \AppBundle\Entity\Subject $subject
 */
public function removeSubject(\AppBundle\Entity\Subject $subject)
{
    $this->subjects->removeElement($subject);
}

/**
 * Get subjects
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getSubjects()
{
    return $this->subjects;
}
}

Subject :

class Subject
{
/**
 * @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;

/**
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Teacher", inversedBy="subjects"))
 */
private $teachers;

/**
 * @ORM\Column(type="string", length=7, nullable=false)
 * @Assert\NotBlank()
 */
public $color;


/**
 * Get id
 *
 * @return integer
 */
public function getId()
{
    return $this->id;
}

/**
 * Set name
 *
 * @param string $name
 *
 * @return Subject
 */
public function setName($name)
{
    $this->name = $name;

    return $this;
}

/**
 * Get name
 *
 * @return string
 */
public function getName()
{
    return $this->name;
}


/**
 * Constructor
 */
public function __construct()
{
    $this->teachers = new \Doctrine\Common\Collections\ArrayCollection();
}


/**
 * Get teachers
 *
 * @return string
 */
public function getTeachers()
{
    return $this->teachers;
}

/**
 * Add teacher
 *
 * @param \AppBundle\Entity\Teacher $teacher
 *
 * @return Subject
 */
public function addTeacher(\AppBundle\Entity\Teacher $teacher)
{
    $this->teachers[] = $teacher;

    return $this;
}

/**
 * Remove teacher
 *
 * @param \AppBundle\Entity\Teacher $teacher
 */
public function removeTeacher(\AppBundle\Entity\Teacher $teacher)
{
    $this->teachers->removeElement($teacher);
}

/**
 * Set color
 *
 * @param string $color
 *
 * @return Subject
 */
public function setColor($color)
{
    $this->color = $color;

    return $this;
}

/**
 * Get color
 *
 * @return string
 */
public function getColor()
{
    return $this->color;
}
}

Upvotes: 1

Views: 681

Answers (1)

Omar Alves
Omar Alves

Reputation: 763

If want a many-to-many relationship, you need a linkage table. You can specify it in annotation, at entity Teacher

/**
 * Owning Side
 * @ManyToMany(targetEntity="Subject", inversedBy="teachers", cascade={"remove"})
 * @JoinTable(name="teacher_subject",
 *      joinColumns={@JoinColumn(name="teacher_id",
 *          referencedColumnName="id", onDelete="CASCADE")},
 *      inverseJoinColumns={@JoinColumn(name="subject_id",
 *      referencedColumnName="id", onDelete="CASCADE")}
 *   )
*/
private $subjects;

and at entity Subject (reverse side)

/**
  * @ManyToMany(targetEntity="Teacher", mappedBy="subjects")
*/
private $teachers;

Drop the @ORM\JoinColumn from $id property at Teacher and

run php app/console doctrine:generate:entities

Upvotes: 1

Related Questions