Clock Blog

Doctrine ORM Associations

Posted on Monday, 28 May 2012 @ 08:07 GMT in tech-blogs by Tom Smith

Doctrine ORM Associations

Doctrine is a set of PHP libraries focused on providing persistence services. Doctrine uses an object relation mapper and database abstraction layer to provide the functionality it offers. See the Doctrine homepage for more general information.

One of the key aspects of Doctrine's ORM is its ability to manage associations between entities. I.e one-to-many, one-to-one, many-to-one, many-to-many. See the associations reference library.

This post will assume a reasonable understanding of relational databases and PHP. As well as a basic understanding of Doctrine.

To help understand how each of the associations are defined a common example of students will be used throughout.

One To one

/**
 * @OneToOne(targetEntity="Address")
 */
protected $address;

Simply specify the TargetEntity on the owning side (in this example this is the Student Entity) and the association is setup. A student has one address. Optionally you can describe the join columns. See @OneToOne

One To Many

/**
 * @OneToMany(targetEntity="Year", mappedBy="students", cascade={"all"})
 */
protected $year;

This is defined in the entity that contains a single item. So in the example a student belongs to only one year. Optionally you can describe the join columns. See @OneToMany

Many To One

/**
 * @ManyToOne(targetEntity="Student", cascade={"all"})
 */
protected $students;

This is defined in the entity that contains multiple items. So in the example a year has many students. See @ManyToOne

Many To Many

With Many to Many relationships there is an owning side and an inverse side. It doesn't matter which entity is the owning side and which is the inversed side. The owning side defines the join table and columns and the inversed side references the owning side.

A student has many classes and a class has many students. If you are storing more information in the join table besides the relationship then a combination of Many to One and One to Many should be used instead using a link entity.

Owning Side

/**
 * @ManyToMany(targetEntity="Class", inversedBy="students")
 * @JoinTable(name="student_to_class",
 *      joinColumns={@JoinColumn(name="student_id", referencedColumnName="id")},
 *      inverseJoinColumns={@JoinColumn(name="class_id", referencedColumnName="id")}
 *      )
 */
protected $classes;

Inversed Side

/**
 * @ManyToMany(targetEntity="Student", mappedBy="classes")
 */
protected $students;
blog comments powered by Disqus