Skip to content
Advertisement

hasManyThrough laravel relation

I have three table below.

+-----------------+   +---------------------+   +-------------+ 
|    products     |   |  product_countries  |   |  countries  |
+-----------------+   +---------------------+   +-------------+ 
|   id            |   |  id                 |   |   id        |
|   name          |   |  product_id         |   |   name      |
|   description   |   |  country_code       |   |   code      |
+-----------------+   |  other columns      |   +-------------+
                      +---------------------+

hasManyThrough in Country::class model to get all products.

public function products()
{
    return $this->hasManyThrough(
        'AppProduct',
        'AppProductCountry',
        'product_id', // Foreign key on feeds table...
        'id', // Foreign key on articles table...
        'code', // Local key on users table...
        'country_code' // Local key on feeds table...
    );
}

I want products which are related to countries or one country:

$user = AppModelsCountry::find(1);
dd($user->products);

Advertisement

Answer

The relation you’re describing best suits a many to many, which is usually written in Laravel as a belongsToMany on both sides.

class Product extends Model
{
    public function countries()
    {
        return $this->belongsToMany(Country::class);
    }
}

class Country extends Model
{
    public function products()
    {
        return $this->belongsToMany(Product::class);
    }
}

If you stick to Laravel’s naming conventions:

  • Rename product_countries to country_product.
  • In country_product use country_id instead of country_code.

…you should be able to access the relations in the way you expect:

$country = AppModelsCountry::find(1);
dd($country->products);

$countries = AppModelsCountry::with('products')->where(...)->get();
foreach ($countries as $country) {
    dd($country->products);
}

If you don’t want to stick to the conventions, you are able to customise how you define the relationships. See Laravel’s documentation for further details.


In your case, to specify your relations using your custom table name and the custom field names you can do this:

// In your Product model
return $this->belongsToMany(Country::class, 'product_countries', 'country_code', 'product_id');

// In your Country model
return $this->belongsToMany(Product::class, 'product_countries', 'product_id', 'country_code');
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement