Many to many relations are one of the mostly used relations in the relational database. It took a while for me to figure how to properly configure this relation in Symfony Doctrine. I am sharing this so it might be useful for someone.
Used very simple example students and course. A student can opt for multiple courses and a single course can be opted by multiple students.
And Entity class should be like this…
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Student
*
* @ORM\Table(name="ab_student")
* @ORM\Entity(repositoryClass="AppBundle\Repository\StudentRepository")
*/
class Student
{
/**
* @var int
*
* @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;
/**
* @var string
*
* @ORM\Column(name="email", type="string", length=255)
*/
private $email;
/**
* @var \DateTime
*
* @ORM\Column(name="dob", type="datetime")
*/
private $dob;
/**
* @var ArrayCollection
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Course", inversedBy="students", fetch="EAGER")
* @ORM\JoinTable(
* name="ab_student_2_course",
* joinColumns={@ORM\JoinColumn(name="course_id", referencedColumnName="id", nullable=false, onDelete="cascade")},
* inverseJoinColumns={@ORM\JoinColumn(name="student_id", referencedColumnName="id", nullable=false, onDelete="cascade")}
* )
*/
private $courses;
public function __construct()
{
$this->courses = new ArrayCollection();
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Student
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set email
*
* @param string $email
*
* @return Student
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set dob
*
* @param \DateTime $dob
*
* @return Student
*/
public function setDob($dob)
{
$this->dob = $dob;
return $this;
}
/**
* Get dob
*
* @return \DateTime
*/
public function getDob()
{
return $this->dob;
}
/**
* @return ArrayCollection
*/
public function getCourses()
{
return $this->courses;
}
/**
* @param ArrayCollection $courses
*/
public function setCourses($courses)
{
$this->courses = $courses;
}
}
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Course
*
* @ORM\Table(name="ab_course")
* @ORM\Entity(repositoryClass="AppBundle\Repository\CourseRepository")
*/
class Course
{
/**
* @var int
*
* @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;
/**
* @var ArrayCollection
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Student", mappedBy="courses", cascade={"all"})
*/
private $students;
public function __construct()
{
$this->students = new ArrayCollection();
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Course
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return ArrayCollection
*/
public function getStudents()
{
return $this->students;
}
/**
* @param ArrayCollection $students
*/
public function setStudents($students)
{
$this->students = $students;
}
}
The above entities will create the following SQL and it will also create the cross-reference table.
CREATE TABLE ab_student
(
id INT auto_increment NOT NULL,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
dob DATETIME NOT NULL,
PRIMARY KEY(id)
)
DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci
engine = innodb;
CREATE TABLE ab_student_2_course
(
course_id INT NOT NULL,
student_id INT NOT NULL,
INDEX idx_87d76467591cc992 (course_id),
INDEX idx_87d76467cb944f1a (student_id),
PRIMARY KEY(course_id, student_id)
)
DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci
engine = innodb;
CREATE TABLE ab_course
(
id INT auto_increment NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY(id)
)
DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci
engine = innodb;
ALTER TABLE ab_student_2_course
ADD CONSTRAINT fk_87d76467591cc992 FOREIGN KEY (course_id) REFERENCES
ab_student (id) ON DELETE CASCADE;
ALTER TABLE ab_student_2_course
ADD CONSTRAINT fk_87d76467cb944f1a FOREIGN KEY (student_id) REFERENCES
ab_course (id) ON DELETE CASCADE;
Hope this helps 😉