Reputation: 221
This is more of a best practices in design question. Given how many possible answers there may be, I'll keep it brief and simple.
I am using FOSUserBundle to provide some basic User management to an application I am building. Imagine for a moment that we have Users in my application and Users could have 1 of 2 types of profiles associated with them (1:1).
What would be a best practice to setting this up? i.e. The user object holds common fields for all users (things like first name, last name, email, etc.) but the other profiles will have varying fields in them.
User
Profile Type A
Profile Type B
I know I need additional classes and some kind of relationship between them so should I...
Profile A/B
class altogether and use inheritance so that my A and B types inherit and extend the User
class? e.g. PrimaryUser
, SomeOtherUser
Thank you so much. It's been a while since I did OO design (missed it though!) and I'm kind of rusty on this sort of thing.
Upvotes: 2
Views: 447
Reputation: 39410
In a similar situation (one user with multiple possibile profile active) we modeling the situation with a one2many from user to roles and the roles table is a doctrine2 Mapped Superclasses with Single Table Inheritance (see this doc).
Some example code for describe the situation:
The User Doctrine Class:
<?php
namespace Acme\SecurityBundle\Entity;
/**
*
* @ORM\Table(name="acme_user")
* @ORM\Entity()
*/
class AcmeUser implements AdvancedUserInterface
{
/**
* One-To-Many
*
* @ORM\OneToMany(targetEntity="Acme\SecurityBundle\Entity\AcmeUserRoles", mappedBy="acmeUser",cascade={"persist"})
*/
protected $acmeRoles;
.....
The Role Doctrine Class:
<?php
namespace Acme\SecurityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\Role\RoleInterface;
/**
* @ORM\Entity
* @ORM\Table(name="acme_user_roles")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"customerRole" = "ACmeCustomerRole", "user" = "AcmeUserRoles","driver" = "AcmeDriverRole"})
*/
class AcmeUserRoles implements RoleInterface
{
/**
* Bidirectional
*
* @ORM\ManyToOne(targetEntity="Acme\SecurityBundle\Entity\AcmeUser", inversedBy="acmeRoles",cascade={"persist"})
* @ORM\JoinColumn(name="acme_user_id", referencedColumnName="id", onDelete="cascade")
*/
protected $acmeUser;
/**
* Bidirectional
*
* @ORM\ManyToOne(targetEntity="Acme\SecurityBundle\Entity\AcmeRole", inversedBy="acmeUserRoles",cascade={"persist"})
* @ORM\JoinColumn(name="acme_role_id", referencedColumnName="id", onDelete="cascade")
*/
protected $acmeRole;
/**
* Implementation of getRole for the RoleInterface.
*
* @return string The role.
*/
public function getRole()
{
return $this->getAcmeRole()->getName();
}
.....
The Role Description Doctrine Class
<?php
namespace Acme\SecurityBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="acme_role")
**/
class AcmeRole
{
const USER_ROLE_NAME = "ROLE_ACME_USER";
const DRIVER_ROLE_NAME = "ROLE_ACME_DRIVER";
....
/**
* @ORM\ManyToMany(targetEntity="AcmeModule", inversedBy="rolePermissionsTemplate")
* @ORM\JoinTable(name="acme_role_permission_template",
* joinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id", onDelete="cascade")},
* inverseJoinColumns={@ORM\JoinColumn(name="module_id", referencedColumnName="id", onDelete="cascade")}
* )
*/
protected $permissionsTemplate;
/**
* One-To-Many
*
* @ORM\OneToMany(targetEntity="Acme\SecurityBundle\Entity\AcmeUserRoles", mappedBy="acmeRole",cascade={"persist"})
*/
protected $acmeUserRoles;
.....
Hope this help
Upvotes: 3