3

I'm creating a website that should have at least two types of users, Company and Client, two of them have the same login form and different registration forms, and they can send messages to each other ...

Normaly (Without think about Doctrine) I think the database should look something like that:
User (id, email, password, facebook_id, roles)
Company(id, user_id, name, city, ...)
Client(id, user_id, name, sex ...)
Messages(id, sender_id(user_id), receiver_id(user_id), message, ...)
...

So now I want to know the best and the simplest way to implement this requirements using Doctrine and Symfony 4, How Entities could look like ?

(Note: I'm not using FOSUserBundle)

Az.Youness
  • 2,167
  • 1
  • 24
  • 33
  • 2
    The doctrine documentation contains a section on managing different types of inheritance, that should help you get going. If you encounter any specific problems, feel free to open a specific question, but I am afraid right now the question is too broad, to be answered meaningfully – dbrumann Nov 13 '18 at 17:44
  • Yeah I find the doctrine documentation section "Inheritance Mapping", I hope I can understand the content because I'm new to the Symfony/Doctrine world .. – Az.Youness Nov 13 '18 at 17:56
  • 2
    No problem, try your luck and when you encounter any problems feel free to ask for help here. Answering to questions with existing code snippets and error messages is always easier than answering open questions. It just means a lot of work and worst case it will still not be as helpful for you as the docs and playing around with it for a bit. :) – dbrumann Nov 13 '18 at 18:01

1 Answers1

6

Implementing this domain:

  • User
  • Company
  • Client

you may consider two different approaches:

First approach

This approach uses association. If you choose this one, you should manually link appropriate (company or client) to the current user depending on some logic. Each User should probably have only one of those field at any given point in time. Company or Client, not both.

User

/** @Entity */
class User
{
    /**
     * @ORM\column(type="string")
     */
    protected password;

    /**
     * @ORM\column(type="array")
     */ 
    protected roles;

    /**
     * @ORM\OneToOne(targetEntity="Company", mappedBy="user")
     */
    protected Company;

    /**
     * @ORM\OneToOne(targetEntity="Client", mappedBy="user")
     */ 
    protected Client;
}

Company

/** @Entity */
class Company
{
    /**
     * @ORM\column(type="string")
     */
    protected city;

    /**
     * @ORM\OneToOne(targetEntity="User", inversedBy="company")
     */ 
    protected user;
}

Client

/** @Entity */
class Client
{
    /**
     * @ORM\column(type="string")
     */
    protected sex;

    /**
     * @ORM\OneToOne(targetEntity="User", inversedBy="client")
     */ 
    protected user;
}

Second approach

This approach uses inheritance and seems to be more flexible, but has its own downsides.

User

/** @MappedSuperclass */
class User
{
    /**
     * @ORM\column(type="string")
     */
    protected password;

    /**
     * @ORM\column(type="array")
     */ 
    protected roles;
}

Company

/** @Entity */
class Company extends User
{
    /**
     * @Id @Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\column(type="string")
     */
    protected city;
}

Client

/** @Entity */
class Client extends User
{
    /**
     * @Id @Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\column(type="string")
     */
    protected sex;
}

You also have a One-To-Many relation between User & Message:

  • One User can have Many Messages
  • One Message belongs to only One User

Using First approach above is fine, but using the Second approach, you are getting yourself in trouble as Doctrine says:

persistent relationships defined by a mapped superclass must be unidirectional (with an owning side only). This means that One-To-Many associations are not possible on a mapped superclass at all.

Peyman Mohamadpour
  • 17,954
  • 24
  • 89
  • 100
  • Thanks, I choose the first approach (Composition), it looks that it's the best way to implement my requirements, the other problem I found with inheritance approach is for example in some steps in my application (registration should be splitted to two steps ..) I will need to update/change User discriminator column, and doing that with Doctrine inheritance is impossible/bad practice .. the problem is described [Here](https://stackoverflow.com/questions/12610421/doctrine-update-discriminator-for-single-table-inheritance) – Az.Youness Nov 14 '18 at 22:31
  • thats ok for now. feel free to ask any other questions on Symfony. please accept && up-vote if was helpful – Peyman Mohamadpour Nov 14 '18 at 22:33