1

Class Table Inheritance is being used to extend Person, to allow for the addition of Employee and Dragon.

A Person, Employee and Dragon can all have a Toys.

How should the connection between Person, Employee, Dragon and Toys be made?

The advantage of Class Table Inheritance seems to be that the relationship can be set on the Parent Entity(Person) avoiding the creation of new Entities called: PersonToy, EmployeeToy and DragonToy.

It would be ideal if code could be written so that $toy->setEmployee($employee), $toy->setDragon($dragon) all worked, internally I assume it must have to do setPerson().

On the opposite side would it be possible to call $toy->getDragon() and $toy->getEmployee() and get a Dragon/Employee and not a Person

I understand that the Entity Toy only has a relationship with Person, but a Person could be extended and therefore be a Dragon or Employee.

How could this be achieved if possible?

/**
 * @Entity
 * @ORM\Table(name="perosn")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"person" = "Person", "employee" = "Employee", "dragon" = "Dragon"})
 */
class Person
{
    /**
     * @ORM\OneToMany(targetEntity="Toy", mappedBy="person")
     */
    protected $toys;

}

/** 
 * @Entity 
 * @ORM\Table(name="employee")
 */
class Employee extends Person
{
    // ...
}

/** 
 * @Entity 
 * @ORM\Table(name="dragon")
 */
class Dragon extends Person
{
    // ...
}

/** 
 * @Entity 
 * @ORM\Table(name="toy")
 */
class Toy {

    /**
     * @ORM\ManyToOne(targetEntity="Person", inversedBy="toys", cascade={"persist"})
     */
    protected $person;        
}
Humayun Shabbir
  • 2,961
  • 4
  • 20
  • 33
lookbadgers
  • 988
  • 9
  • 31
  • Could you do something more general like $toy->setOwner($person)? That way if you extend the class in the future you don't have to add setters for the new type. If you want different actions based on the owner, you could add a playWith method to each class. $toy->getOwner()->playWith($toy). – Quint Aug 01 '14 at 16:07
  • How would setOwner work internally? function setOwner(Person $person) { $this->person = $person; } I guess you could then have a getOwner() but how would that work, because it would need to return a Dragon, Employee or Person. – lookbadgers Aug 01 '14 at 16:19
  • It could work a couple of ways. One, you could leave off the type hinting, use duck typing and just assume that the right thing will be there. Two, you could create an interface (PersonInterface) and not worry about the underlying class. The function would then be setOwner(PersonInterface $owner). Then the playWith() function would be part of the interface and you could use the Person playWith() function or write one in the subclass. – Quint Aug 01 '14 at 16:30
  • I would agreee with using PersonInterface, but when you look inside the setOwner method you would have $this->person = Dragon $owner; When Doctrine comes to persist the relationship the targetEntity for person is Person so it would throw an exception about Dragon not being a Person. – lookbadgers Aug 01 '14 at 16:55
  • I don't think that will be a problem. Doctrine introspects the object to figure out its class when persisting. You don't have to do type coercion to set it explicitly. You can just call $em->persist($this->owner) regardless of what type of thing owner is. – Quint Aug 01 '14 at 20:18

0 Answers0