Skip to content

Instantly share code, notes, and snippets.

@jaspernbrouwer
Created December 8, 2012 14:34
Show Gist options
  • Save jaspernbrouwer/4240472 to your computer and use it in GitHub Desktop.
Save jaspernbrouwer/4240472 to your computer and use it in GitHub Desktop.
Basic Doctrine 2 one-to-many/many-to-one association setup
<?php
/*
* This is a basic setup for Doctrine 2 one-to-many/many-to-one associations.
*
* There are many alternative approaches, additions and optimizations possible,
* but this example is only meant to help people getting started with the concept.
*/
namespace My\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity
* @ORM\Table( name="person" )
*/
class Person
{
/**
* @ORM\Column( type="integer" )
* @ORM\GeneratedValue( strategy="IDENTITY" )
* @ORM\Id
* @var int
*/
protected $id;
/**
* @ORM\Column( type="string" )
* @var string
*/
protected $name;
/**
* @ORM\OneToMany( targetEntity="My\Entity\Membership", mappedBy="person", orphanRemoval=TRUE )
* @var \Doctrine\Common\Collections\Collection
*/
protected $memberships;
/**
* Constructor.
*/
public function __construct()
{
$this->memberships = new ArrayCollection();
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
* @return \My\Entity\Person
*/
public function setName( $name )
{
$this->name = $name;
return $this;
}
/**
* @return array
*/
public function getMemberships()
{
return $this->memberships->toArray();
}
/**
* @param \My\Entity\Group $group
* @return \My\Entity\Membership|null
*/
public function getMembershipByGroup( Group $group )
{
foreach( $this->memberships as $membership ) {
if( $membership->getGroup() === $group ) {
return $membership;
}
}
return null;
}
/**
* @return array
*/
public function getGroups()
{
$groups = $this->memberships->map(
function( $membership ) {
return $membership->getGroup();
}
);
return $groups->toArray();
}
/**
* @param \My\Entity\Group $group
* @return \My\Entity\Person
*/
public function removeGroup( Group $group )
{
foreach( $this->memberships as $membership ) {
if( $membership->getGroup() === $group ) {
$this->memberships->removeElement( $membership );
// sync other side of one-to-many/many-to-one association
$group->removePerson( $this );
}
}
return $this;
}
/**
* For internal use, never call directly.
*
* @internal
* @param \My\Entity\Membership $membership
* @return \My\Entity\Person
*/
public function addMembership( Membership $membership )
{
$this->memberships->add( $membership );
return $this;
}
}
/**
* @ORM\Entity
* @ORM\Table( name="membership" )
*/
class Membership
{
/**
* @ORM\Column( type="integer" )
* @ORM\GeneratedValue( strategy="IDENTITY" )
* @ORM\Id
* @var int
*/
protected $id;
/**
* @ORM\Column( type="string" )
* @var string
*/
protected $type;
/**
* @ORM\ManyToOne( targetEntity="My\Entity\Person", inversedBy="memberships" )
* @ORM\JoinColumn( name="person_id", referencedColumnName="id", nullable=FALSE )
* @var \My\Entity\Person
*/
protected $person;
/**
* @ORM\ManyToOne( targetEntity="My\Entity\Group", inversedBy="memberships" )
* @ORM\JoinColumn( name="group_id", referencedColumnName="id", nullable=FALSE )
* @var \My\Entity\Group
*/
protected $group;
/**
* Constructor.
*
* @param \My\Entity\Person $person
* @param \My\Entity\Group $group
*/
public function __construct( Person $person, Group $group )
{
$this->person = $person;
$this->group = $group;
// sync other side of many-to-one associations
$person->addMembership( $this );
$group->addMembership( $this );
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @param string $type
* @return \My\Entity\Membership
*/
public function setType( $type )
{
$this->type = $type;
return $this;
}
/**
* @return \My\Entity\Person
*/
public function getPerson()
{
return $this->person;
}
/**
* @return \My\Entity\Group
*/
public function getGroup()
{
return $this->group;
}
}
/**
* @ORM\Entity
* @ORM\Table( name="group" )
*/
class Group
{
/**
* @ORM\Column( type="integer" )
* @ORM\GeneratedValue( strategy="IDENTITY" )
* @ORM\Id
* @var int
*/
protected $id;
/**
* @ORM\Column( type="string" )
* @var string
*/
protected $name;
/**
* @ORM\OneToMany( targetEntity="My\Entity\Membership", mappedBy="group", orphanRemoval=TRUE )
* @var \Doctrine\Common\Collections\Collection
*/
protected $memberships;
/**
* Constructor.
*/
public function __construct()
{
$this->memberships = new ArrayCollection();
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
* @return \My\Entity\Group
*/
public function setName( $name )
{
$this->name = $name;
return $this;
}
/**
* @return array
*/
public function getMemberships()
{
return $this->memberships->toArray();
}
/**
* @param \My\Entity\Person $person
* @return \My\Entity\Membership|null
*/
public function getMembershipByPerson( Person $person )
{
foreach( $this->memberships as $membership ) {
if( $membership->getPerson() === $person ) {
return $membership;
}
}
return null;
}
/**
* @return array
*/
public function getPeople()
{
$people = $this->memberships->map(
function( $membership ) {
return $membership->getPerson();
}
);
return $people->toArray();
}
/**
* @param \My\Entity\Person $person
* @return \My\Entity\Group
*/
public function removePerson( Person $person )
{
foreach( $this->memberships as $membership ) {
if( $membership->getPerson() === $person ) {
$this->memberships->removeElement( $membership );
// sync other side of one-to-many/many-to-one association
$person->removeGroup( $this );
}
}
return $this;
}
/**
* For internal use, never call directly.
*
* @internal
* @param \My\Entity\Membership $membership
* @return \My\Entity\Group
*/
public function addMembership( Membership $membership )
{
$this->memberships->add( $membership );
return $this;
}
}
/*
* Using this setup.
*
* First person, group and membership:
*/
$person1 = new Person();
$person1->setName( 'John Doe' );
$group1 = new Group();
$group1->setName( 'Anonymous' );
// this will also add membership to person and group:
$membership1 = new Membership( $person1, $group1 );
$membership1->setType( 'follower' );
$em->persist( $person1 );
$em->persist( $group1 );
$em->persist( $membership1 );
$em->flush();
/*
* Second person, add it to the same group:
*/
$group1 = $em->find( 'My\Entity\Group', 1 );
$person2 = new Person();
$person2->setName( 'Jane Doe' );
// this will also add membership to person and group:
$membership2 = new Membership( $person2, $group1 );
$membership2->setType( 'follower' );
$em->persist( $person2 );
$em->persist( $membership2 );
$em->flush();
/*
* Change type of membership of second person:
*/
$person2 = $em->find( 'My\Entity\Person', 2 );
$group1 = $em->find( 'My\Entity\Group', 1 );
$membership = $person2->getMembershipByGroup( $group1 );
$membership->setType( 'leader' );
$em->flush();
/*
* Remove first person from the group:
*/
$person1 = $em->find( 'My\Entity\Person', 1 );
$group1 = $em->find( 'My\Entity\Group', 1 );
// this will also remove person from group, and delete membership from db due to orphan-removal:
$person1->removeGroup( $group1 );
$em->flush();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment