FabCol's avatar

belongsToMany, pivot table and multiple condition

Hi All, I'm suffering. Not (yet a master at eloquent lol).

I have: One table: messageTopics One table: users A belongsToMany relation between both.

In table message_topic, I have a 'sender_id' field. Sender is unique, so it can be directly in this table. Receivers (which are indeed users) can be multiple. So 'belongsToMany' in a table called messageTopics_users, with fields topic_id and receiver_id.

My model: public function receiver() { return $this->belongsToMany(User::class, 'messageTopics_users', 'message_id' ,'receiver_id'); }

For a given "$userId = Auth::user()->id;" I'm trying to get:

  • ALL the messages he sent
  • ALL the messages he received

Everything is the sale $topics result. So it's two conditions, one in messageTopics table and one in the pivot table.

I tried many things... nothing works....

Any idea?

Thanks FAB

0 likes
13 replies
Vilfago's avatar

In your user model you should set 2 relations.

  • topicSent (hasMany)
  • topicReceived (belongsToMany (i.e. Many-to-Many))

And then, load your 2 relations.

FabCol's avatar

OK, got it.

And what would be the correct syntax to then get both in the same result?

Vilfago's avatar
$users = User::with('topicsSent')->with('topicsReceived')->get();

dd($users);

Something like that

FabCol's avatar

Of course! "with" twice! Didn't think about that... THANKS!

Cronix's avatar

or using a single with $users = User::with(['topicsSent', 'topicsReceived'])->get();

FabCol's avatar

Execept I'm not looking for the users... but for the messages.

So it doesn't work.

So far, I get that working:

$receivedTopics = Messengertopic::whereHas('receiver', function ($query) use ($userId) { $query->where('id', $userId); })->get();

$sentTopics = MessengerTopic::where('sender_id', $userId)->orderBy('sent_at', 'desc')->get();

But I also need $topics, combining both results above ordered by date...

Vilfago's avatar

For a given "$userId = Auth::user()->id;" I'm trying to get:

So... what do you need ?

With the relation, you retrieve one user, and in the relation of the collection, all these messages.

FabCol's avatar

For a given "$userId" I'm trying to get:

ALL the messages he sent ALL the messages he received

FabCol's avatar

Actually, my problem can be recap as this:

HOW to combine those two things

$receivedTopics = Messengertopic::whereHas('receiver', function ($query) use ($userId) { $query->where('id', $userId); })->get();

$sentTopics = MessengerTopic::where('sender_id', $userId)->orderBy('sent_at', 'desc')->get();

$allTopics=???????;

Vilfago's avatar
Vilfago
Best Answer
Level 20
$user = User::with('topicsSent')->with('topicsReceived')->find(Auth::id());

$receivedTopics = $user->topicsReceived;
$sentTopics = $user->sentTopics;
$allTopics = $receivedTopics->merge($sentTopics); //be carefull, I don't know if it will erase some data considered as duplicate.
Vilfago's avatar

Or ask the inverse relationship, something like :

$user_id = Auth::id(); //I'm not sure that Auth::id() is available in anonymous function... so just in case.
$allTopics = Topics::whereHas('receiver', function ($query) use ($user_id) {
        $query->where('receiver_id', '=', $user_id);
    })
    ->orWhereHas('sender', function ($query) use ($user_id) {
        $query->where('sender_id', '=', $user_id);
    })->get();
FabCol's avatar

merge! That exactly what I was looking for :-)

Big thanks!

Vilfago's avatar

My pleasure.

Mark it at resolve to keep this forum clean.

Please or to participate in this conversation.