Mathias
Mathias

Reputation: 207

Doctrine Inheritance and user types

im new to Doctrine and ORM in general.

I got 4 user types (Admin, Caretaker, Child, Personal). They all got some of the same columns (id, name, mail, password, created, type & group) and they got a few columns special to each of them (Caretaker has a child id etc.)

I'm not quite sure how i should map this. Like should i make my user types extend the User, giving the Child table the user columns, or what would be best practice here?

I assume the the option to use extend would force some more work when doing a login?

User.php

/**
 * @MappedSuperclass
 * @Entity @Table(name="users")
 */
class User
{
    /**
     * @Id @GeneratedValue @Column(type="integer")
     * @var int
     **/
    protected $id;
    /**
     * @Column(type="string")
     * @var string
     **/
    protected $name;
    /**
     * @Column(type="string")
     * @var string
     **/
    protected $mail;
    /**
     * @Column(type="string")
     * @var string
     **/
    protected $password;
    /**
     * @Column(type="datetime")
     **/
    protected $created;
    /**
     * @Column(type="datetime")
     **/
    protected $lastlogin;
    /**
     * @ManyToOne(targetEntity="Group")
     * @JoinColumn(name="group_id", referencedColumnName="id")
     */
    protected $group;

    /**
     * @ManyToOne(targetEntity="Type")
     * @JoinColumn(name="type_id", referencedColumnName="id")
     */
    protected $type;

    public function __construct() {}

    public function getId() { return $this->id; }

    public function getName() { return $this->name; }

    public function getMail() { return $this->mail; }

    public function getCreated() { return $this->mail; }

    public function getLastLogin() { return $this->lastlogin; }

    public function getGroup() { return $this->group; }

    public function getType() { return $this->type; }

    public function setName($name) { $this->name = $name; }

    public function setMail($mail) { $this->mail = $mail; }

    public function setCreated() { $this->created = new DateTime("now"); }

    public function setLastLogin() { $this->lastlogin = new DateTime("now"); }

    public function setGroup($group) { $this->group = $group; }

    public function setType($type) { $this->type = $type; }
}

Child.php

// src/Child.php
use Doctrine\Common\Collections\ArrayCollection;
/**
 * @Entity @Table(name="child")
 */
class Child extends User
{
    /**
     * @Id @OneToOne(targetEntity="User")
     * @JoinColumn(name="id", referencedColumnName="id")
     **/
    protected $id;
    /**
     * @Column(type="string")
     */
    protected $image;
    /**
     * @ManyToMany(targetEntity="User")
     * @JoinTable(name="child_Contacts",
     *      joinColumns={@JoinColumn(name="child_id", referencedColumnName="id")},
     *      inverseJoinColumns={@JoinColumn(name="contact_id", referencedColumnName="id")}
     *      )
     */
    protected $currentContacts;
    /**
     * @OneToMany(targetEntity="Alarm", mappedBy="child")
     */
    protected $alarms;

    public function __construct()
    {
        $this->alarms = new ArrayCollection();
    }
}

Upvotes: 2

Views: 915

Answers (1)

Florian Cabirol
Florian Cabirol

Reputation: 185

You can easily solve this problem with doctrine and InheritanceType mapping.

Basically, you can do something like this :

/**
 * @MappedSuperclass
 * @Entity @Table(name="users")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"Admin" = "Admin", "Caretaker" = "Caretaker", "Child" = "Child", "Personal" = "Personal"})
 */
class User
{
    /**
     * @Id @GeneratedValue @Column(type="integer")
     * @var int
     **/
    protected $id;
    /**
     * @Column(type="string")
     * @var string
     **/
    protected $name;
    /**
     * @Column(type="string")
     * @var string
     **/
    protected $mail;
    /**
     * @Column(type="string")
     * @var string
     **/
    protected $password;
    /**
     * @Column(type="datetime")
     **/
    protected $created;
    /**
     * @Column(type="datetime")
     **/
    protected $lastlogin;
    /**
     * @ManyToOne(targetEntity="Group")
     * @JoinColumn(name="group_id", referencedColumnName="id")
     */
    protected $group;
}

And then, in each 4 different classes,

// src/Child.php
use Doctrine\Common\Collections\ArrayCollection;
/**
 * @Entity @Table(name="child")
 */
class Child extends User
{
    /**
     * @Id @OneToOne(targetEntity="User")
     * @JoinColumn(name="id", referencedColumnName="id")
     **/
    protected $id;
    /**
     * @Column(type="string")
     */
    protected $image;
    /**
     * @ManyToMany(targetEntity="User")
     * @JoinTable(name="child_Contacts",
     *      joinColumns={@JoinColumn(name="child_id", referencedColumnName="id")},
     *      inverseJoinColumns={@JoinColumn(name="contact_id", referencedColumnName="id")}
     *      )
     */
    protected $currentContacts;
    /**
     * @OneToMany(targetEntity="Alarm", mappedBy="child")
     */
    protected $alarms;

    public function __construct()
    {
        $this->alarms = new ArrayCollection();
    }
}

The doctrine docs is really good for this problem : http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html

And you don't need an extra check at login because doctrine create automatically the right class for you.

Upvotes: 2

Related Questions