php - Laravel: pivot table extra field in model

Let's assume I've got a User model and the Country model. User could have up to four countries simultaneously (home country and three countries he'd like to visit). Using Eloquent, I'd create a pivot able country_user with an extra field of type, that would correspond to the choice of the user, which country he'd put in the first place etc. So once again, there is:

    User
     --id

    Country
     --id

    country_user
     --id
     --user_id
     --country_id
     --type

I need to get all users who have, let's say, Canada as a country type 1, UK as a country type 2, France as a country type 3 and New Zealand as a country type 4. If I understand correctly then I can't use wherePivot to do this, only if I get a User::all() and iterate through this collection (which doesn't make much sense and puts unnecessary load on the DB). What could be the proper way to do this with a minimum possible amount of queries to DB? Or do I get it all wrong and there should be another approach to this task at all?

Answer

Solution:

You can still search on the pivot table using the relationship you have defined between a User and Country. If for the sake of this example we call that relationship countries and that you want to find people with the following $criteria (sticking to your example):

$criteria = [
    'canada' => 1,
    'uk' => 2,
    'france' => 3,
    'new zealand' => 4,
];

So the key in the above is the Country and the value is the type.

To find Users that have those exact requirements, you could do the following:

$users = User::whereHas('countries');

collect($criteria)->each(function ($type, $country) use ($users) {
    $users->whereHas('countries', function (Builder $query) use ($type, $country) {
        $query->where(['name' => $country, 'type' => $type]);
    })->get();
});

Then do something with your $users.

$users->get();

Answer

Solution:

You can the country relationship of HasMany

So, in users it would be this

public function countries() {
     return $this->hasMany('country_user_class', 'foreign_key_id_here')->latest()->take(4); // take 4 since the user can have 4 countries
}

The query would look something like this.

User::whereHas('countries', function($query) {
    $query->where('type', [1,2,3,4]);
})->get();

This would give you the result. This is how you can achieve it using Query. Such a problem can always be solved by Query. Let me know if you've any more question regarding this.

Source