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

valentinmorice's avatar

Eloquent Many to Many

Hi there, I'm currently working on a booking application and am trying to figure out my database schemes and Eloquent relationships. I have the following tables: users, bookings, rooms, and booking_rooms. A booking belongs to many rooms, and a room belongs to many bookings. I managed to implement the many to many relationship successfully, and can retrieve rooms associated with a particular booking by using

$booking = App\Models\Booking::find($id);
$booking->rooms;

However, each booking belongs to a single user. If I do

$booking = App\Models\User::find($id)->bookings->where('id', $id);
$booking->rooms;

I am met with the following error:

Exception with message 'Property [rooms] does not exist on this collection instance.'

Why is that?

0 likes
11 replies
Sinnbeck's avatar

Why would the bookings and user share the id ?

Anyways. You just want the first booking ?

$booking = App\Models\User::find($id)->bookings()->first();
$booking->rooms;
1 like
rodrigo.pedra's avatar

@Sinnbeck nice to see you around my friend. Hope you are doing fine.

You always beat me on answering faster. I guess I need to train my typing skills or become more succinct =)

1 like
Sinnbeck's avatar

@rodrigo.pedra Same to you my friend. Hope to see you a Laracon later today! Well you answers are always a lot longer than mine, but also way better :) Your answers are often good enough to be a blog post :) I have sadly had bad experiences where I wrote a loong post, only to find out that the problem was something completely different :)

1 like
rodrigo.pedra's avatar

@Sinnbeck I won't make to Laracon today, as it will be in business hours down here, but I am planning on going to Laracon EU next year if Lisbon is confirmed.

I thought on starting a blog, but am still not very confident on my English skills.

Thanks for the compliment, but you are being modest. I wish I was more direct to the point like you usually are.

Also congrats on your blog, I always keep an eye on it, but I must confess I sometimes notice new posts after @tray2 retweets it =)

Please consider adding a RSS feed if not much trouble. Both you and @Tray2

1 like
Sinnbeck's avatar

@rodrigo.pedra Ah too bad! I am allowed to take time off work to watch it luckily :)

Would love to go to Lisbon to attend. Will need to see if I can find the money :)

I think your english is great, and feel free to send over the .md files before publishing. I always proof read for @tray2 and he does the same for me :)

I will look into RSS :)

2 likes
rodrigo.pedra's avatar
Level 56

Let's break this statement in pieces:

$booking = App\Models\User::find($id)->bookings->where('id', $id);

First step

App\Models\User::find($id)

User::find() will execute a query in the users table and return a User instance.

So up here you will have a User object

Second step

App\Models\User::find($id)->bookings

You are now asking Laravel to execute a query and retrieve all bookings belonging to the user.

Note you define this relationship as a method, but when we call it as a property, Laravel understands you want it to execute a query and return its results.

As the relation is a belongs to many, we end up with a Collection instance here.

Third step

App\Models\User::find($id)->bookings->where('id', $id)

Now you are calling the Collection@where method. This method filters down the collection, but the result is still a collection object, even if it has only an item.

https://laravel.com/docs/9.x/collections#method-where

Side note: I guess here you would want to use a different $id than the one used to find the user. Most probably you want a specific booking id.

Epilogue

So when calling

$booking->rooms;

Laravel errors out saying there is no rooms property on the collection object filtered in the last statement we broke down.

Solutions

You can use a different collection method to filter down to a single instance, both the following will do, but you can look at the docs on more:

$booking = App\Models\User::find($id)->bookings->where('id', $id)->first();

or

$booking = App\Models\User::find($id)->bookings->firstWhere('id', $id);

Hope this helps =)

2 likes
Snapey's avatar

@rodrigo.pedra nothing wrong with your english 👍

but happy to be your english proof reader if it gives you more confidence

1 like
rodrigo.pedra's avatar

@Snapey thanks a lot !

I will try to come up with some ideas for a blog post, maybe later this year =)

valentinmorice's avatar

Oh, sorry, I didn't realize I was replicating the same $id in the code snippet. What I meant to say is, if I query the booking directly from the Booking model, i can get the rooms. If i query the booking from the User model, then I cannot access the rooms. Like so:

$booking = App\Models\Booking::find($id); // Get a specific booking
$booking->rooms  // That works

$user = App\Models\User::find($id); // Get a specific user, associated with the booking 
$booking = $user->bookings->where('id', $id); // Get same booking as above, but from the user model
$booking->rooms  // That does not work

Hope that's clear.

Edit: Solved the problem with @rodrigo.pedra's answer. Thank you!

1 like
MichalOravec's avatar

Why not like this:

$booking = Booking::where('user_id', $userId)->findOrFail($id);

$booking->rooms;
1 like

Please or to participate in this conversation.