Wcan
Wcan

Reputation: 878

Laravel pivot model relationship with another table

enter image description here

Database Explanation:

The Problem: In eloquent query I am able to fetch data until option_type, I don't know how to create relationship of option_type pivot model with size model.

Eloquent Query:

$items = Item::with(['tiers' => function ($query) {
            $query->with(['type' => function($query) {
                $query->with('sizes')
                    ->with('options')
                    ->with('addons');
            }]);
        }])->where('id', 1)->get();
        return $items;

What I want to Achieve: I want to eager load option_type with sizes, for every optiontype row i may have size and its price.

The Problem: when i write a query like:

$query->with(['options' => function($query) {
    $query->with('sizes);
}])

It is basically saying that options have relationship with sizes which is not right, it should be optionType have relationship with size. how to can i get the data so that i would show me for record for each optiontype_id, size_id and price.

Type Model:

class Type extends Model
{
    protected $table = 'types';

    public function options()
    {
        return $this->belongsToMany(Option::class);
    }
}

Option Model:

class Option extends Model
{
    public function type()
    {
        return $this->belongsToMany(Type::class);
    }
}

OptionType Model:

use Illuminate\Database\Eloquent\Relations\Pivot;

class OptionType extends Pivot
{
    protected $table = 'option_type';

    public function optiontypesize()
    {
        return $this->belongsToMany(Size::class, 'option_type_size', 'size_id', 'option_type_id');
    }
}

Size Model:

class Size extends Model
{
    public function optiontypesize()
    {
        return $this->belongsToMany(OptionType::class, 'option_type_size', 'size_id', 'option_type_id');
    }
}

Upvotes: 3

Views: 1754

Answers (1)

Wcan
Wcan

Reputation: 878

I have solved the problem myself, I will write the detailed answer here in case if someone ran into same problem in future.

I have modified the database but the concept of problem remains the same.

enter image description here

Explanation:

  • items has many tiers
  • tiers has one type
  • tiers has many options and options has many tiers (bringing the option_tier table in scene)
  • option_tier has many sizes and sizes has many option_tier (bringing the option_tier_price table in scene, with an additional field of 'price')

Solutions: I am using AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait for eager loading pivot relations. The concept is taken from this article https://medium.com/@ajcastro29/laravel-eloquent-eager-load-pivot-relations-dba579f3fd3a The only difference is i have changed the relationship from belongTo to hasMany and it works like a charm.

Tier Model:

use AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait;

class Tier extends Model
{
    use EagerLoadPivotTrait;
    protected $table = 'tiers';

    public function options()
    {
        return $this->belongsToMany(Option::class, 'option_tier')
            ->using(OptionTier::class)
            ->withPivot('id');
    }
}

Option Model:

use AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait;

class Option extends Model
{
    use EagerLoadPivotTrait;

    protected $table = 'options';
    
    public function tiers()
    {
        return $this->belongsToMany(Tier::class, 'option_tier');
    }
}

OptionTier Model:

use AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait;
use Illuminate\Database\Eloquent\Relations\Pivot;

class OptionTier extends Pivot
{
    use EagerLoadPivotTrait;
    
    protected $table = 'option_tier';
    
    public function price()
    {
        return $this->hasMany(OptionTierPrice::class, 'option_tier_id');
    }
}

OptionTierPrice Model:

use AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait;

class OptionTierPrice extends Model
{
    use EagerLoadPivotTrait;
    
    protected $table = 'option_tier_price';
    
    public function size()
    {
        return $this->belongsTo(Size::class);
    }
}

Controller:

$tiers = Product::with(['tiers' => function($query) {
    $query->with(['type'])
          ->with(['sizes'])
          ->with(['options.pivot.price.size'])
          ->with(['addons.pivot.price.size']);
}])
->get();
return $tiers;

Upvotes: 3

Related Questions