Konrad Nowacki
Konrad Nowacki

Reputation: 11

Allowing Symfony 4 and Doctrine for duplicate ManyToMany relations

I want to create ManyToMany relation with duplicate options. One USER can have many CARS and many CARS can belong to various USERs. At the same time, one USER can own many cars of the same type.

How do I solve this in Symfony 4 and Doctrine?

Upvotes: 1

Views: 267

Answers (1)

cezar
cezar

Reputation: 12012

Presumably you have two entities, as described, User and Car, and define a ManyToMany relation between them. It could look like this:

User.php

class User
{
    // ...
    /**
     * @ManyToMany(targetEntity="App\Entity\Car", inversedBy="users")
     */
    private $cars;
    // ...
}

Car.php

class Car
{
    // ...
    /**
     * @ManyToMany(targetEntity="App\Entity\User", mappedBy="cars")
     */
    // ...
    private $users;
}

Doctrine will automatically create an intermediate table between them, something like users_cars with two columns: user_id and car_id. They will hold the foreign keys to users and cars respectively. Your problem is that Doctrine creates a composite primary key of these two columns, which means it must be unique and you can't have something like:

 user_id | car_id
------------------
   1     |   1
   1     |   1

which should be for example something like:

Konrad | Porsche 911
Konrad | Porsche 911

With other words, Konrad has two cars of the same model.

You could break the ManyToMany relation into two ManyToOne and define your own entity for the intermediate table:

Ownership.php

class Ownership
{
    // ...
    /**
     * @ManyToOne(targetEntity="App\Entity\User", inversedBy="cars_owned")
     */
    private $user;

    /**
     * @ManyToOne(targetEntity="App\Entity\Car", inversedBy="owners")
     */
    private $car;
    // ...
}

Set up the appropriate OneToMany relations in User and Car. Now you can have duplicates in your table ownerships. This gives you the flexibility to add more information about the ownership, maybe purchase date when the user has acquired the car.

I'd like to stress that naming is one of the most important things in programming. Name your classes and methods with some forethought. What to they describe, what do they do?

To me it wasn't immediately obvious how a user can own the same car more then once. I was thinking of a physical vehicle by the term car. Maybe you should rather call that entity CarModel or CarBrand. Also User isn't very intuitive, I'd rather choose Owner or Person, but this depends on the further business logic of your application.

Upvotes: 2

Related Questions