Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

axis's avatar
Level 1

Accessing data over two many-to-many relationships

Hi, i try to access data over 2 belongsToMany relationships.

I've 5 tables : markets, benefit_market, benefits, benefit_item, items and these 3 models behind.

Markets have multiple benefits and benefits have multiple items

//Market.php

class Market extends Model
{
    public function benefits()
    {
        return $this->belongsToMany(Benefit::class);
    }
}
//Benefit.php

class Benefit extends Model
{
    public function items()
    {
        return $this->belongsToMany(Item::class);
    }

    public function markets()
    {
        return $this->belongsToMany(Market::class);
    }
}
//Item.php

class Item extends Model
{
    public function benefits()
    {
        return $this->belongsToMany(Benefit::class);
    }
}

I want to access all items for a given market (and reverse access all markets for given items) like this : $market->items but i don't know how to do it.

I've tried $market->with(benefits.items)->get() but i can't access directly to all items for the market...

Hope someone can help me. Thanks. :)

0 likes
17 replies
bugsysha's avatar

Does this work?

$market->with(benefits.items)->pluck('benefits.items');
axis's avatar
Level 1

Thanks for your reply bugsysha but it doenst work.

I'va "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'benefits.items' in 'field list' (SQL: select benefits.items from markets)" error...

:-(

axis's avatar
Level 1

When i do $market->with(benefits.items)->get() i've a collection of all markets. Each market has for relation a collection of benefits who have items....

bugsysha's avatar

Did Laravel receive a hasManyThrough() relationship that you can use?

axis's avatar
Level 1

I havent hasManyThrough() relation.

Markets -> Benefits = BelongsToMany
Benefits -> Items = BelongsToMany

I've two pivot tables : benefit_market (benefit_id, market_id) & benefit_item (beneift_id, item_id)

I can't make hasManyThroug() relation cross all tables no ?

bugsysha's avatar

Nope. I've read belongsToMany as hasMany.

bugsysha's avatar

Post a dummy table which I can use to find a solution.

axis's avatar
Level 1

For me, i must implement a new relation in Market model but i don't know how i can do this...

Market.php

public function items()
{
    return ???
}
axis's avatar
Level 1

Somebody else have an idea ?

drgreen's avatar
drgreen
Best Answer
Level 28

Try something like this: https://stackoverflow.com/a/26187648

Or you can use an accessor to your Market model:

public function getItemsAttribute()
{
    return $items = $this->benefits->pluck('items')->collapse()->unique('id');
}

Then in your controller you can do something like this:

$market = Market::with('benefits.items')->first();
dd($market->items);

// or this
$markets = Market::with('benefits.items')->get();
foreach($markets as $market) {
    dd($market->items);
}
axis's avatar
Level 1

Thanks a lot drgeen !!

$market->benefits->pluck('items')->collapse() works perfectly :)

axis's avatar
Level 1

i've an other question : is there a way to paginate item collection ?

drgreen's avatar

Not related to the paginate question.

Remember to eager load the relationships or lazy eager load it before calling the accessor to avoid N+1 query problem.

// eager load
$markets = Market::with('benefits.items')->get();
$market = Market::with('benefits.items')->first();

// lazy eager load
$market->load('benefits.items');    
// or this
$market->loadMissing('benefits.items');

Refer here for Lazy Eager Loading

axis's avatar
Level 1

However i use eager load or not i've the same error : BadMethodCallException Method Illuminate\Support\Collection::paginate does not exist.

This is my controller :

// MarketController.php

    public function show(Market $market)
    {
        $market->loadMissing('benefits.items');
        $items = $market->items->paginate(10);

        return view('pages.markets.show', compact('market', 'items'));
    }
drgreen's avatar

Maybe you can use this for paginated result:

public function show(Market $market)
{
    $items = Item::whereHas('benefits', function ($query) use ($market) {
        $query->whereHas('markets', function ($q) use ($market) {
            $q->where('markets.id', $market->id);
        });
    })->paginate(5); // 5 results each page

    return view('pages.markets.show', compact('market', 'items'));
}

Please or to participate in this conversation.