Simone M
Simone M

Reputation: 21

Doctrine relation between entities based on a field value

I have a problem with Doctrine 2 & Symfony.

I have a User entity, and three entities Example1, Example2, Example3 I want to link with.

I would like to define a many2one relation between User and one of these three classes Example1, Example2, Example3, basing it on the value of $relation_type and $parent in User.

I was thinking to define an abstract class Player so Example1, Example2, Example3 can extend from it, but I do not know how to go on ...

Any suggestions?

class User
{
    /* ... */
    private $relation_type;

    /**
     * @var \AppBundle\Entity\Player
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Player")
     * @ORM\JoinColumn(name="parent", referencedColumnName="id")
     */
    private $parent;

}

class Player
{

}

class Example1 extends Player
{

}

Upvotes: 2

Views: 675

Answers (2)

Cristian Dumitru
Cristian Dumitru

Reputation: 641

You might be looking for STI which is basically an implementation for polymorphic data.

If I correctly understood your use-case I would recommend the following Structure

users[id, ..]
| 1-2-M
players[id, type, user_id, ..]

(*You could go further and create +1 table for each of the Examples to store specific data)

In Doctrine/Symfony that would translate into

<?PHP
/**
 * @ORM\Entity()
 * @ORM\Table(name="users")
 */
class User {
}

-

<?PHP 
/**
 * @ORM\MappedSuperclass
 * @ORM\Entity
 * @ORM\Table(name="players")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({
 *     "Example1" = "AppBundle\Entity\Players\Example1",
 *     "Example2" = "AppBundle\Entity\Players\Example2",
 *     "Example3" = "AppBundle\Entity\Players\Example3",
 *     "undefined" = "Player"
 * })
 */
abstract class Player
{

/**
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 * @ORM\Column(type="integer", options={"unsigned"=true})
 */
protected $id;

/**
 * @ORM\ManyToOne(targetEntity="User", inversedBy="profiles", fetch="EAGER")
 * @ORM\JoinColumn(nullable=false)
 */
protected $user;
}

-

/**
 * @ORM\Entity
 */
class Example1 extends Player implements PlayerInterface
{
}

Upvotes: 0

Wilt
Wilt

Reputation: 44336

If Player is an abstract class then you can mark it as a mapped superclass with the @MappedSuperClass annotation.
Check also the Doctrine2 documentation chapter 6.1. Mapped SuperClasses for more details.

<?php
/** @MappedSuperclass */
class Player
{
    //common properties
}

And now you can extend Player in your subclass:

<?php
/** @Entity */
class Example1 extends Player
{
    //example1 specific properties.
}

Using mapped superclasses comes with its limitations. Read the documentation carefully to understand what is possible and what isn't.

Upvotes: 0

Related Questions