Laravel与当前用户参与的所有参与者进行所有对话

I have four tables. User, Conversations, Message and Conversation_Participants. I hope you don't find a relationship error in this image(I hope you don't find a relationship error in this image )

I tried to add a function

public function conversations(){

    return $this->belongsToMany(Conversation::class, 'conversation_participants', 'user_id', 'conversation_id');
}

to User::class but if i call User::with('conversations')->get() i only get all existing Users. What am I doing wrong? First i want to get all conversations the current user participates in and second I want to get all receivers of the conversations.

I also tried

public function participants()
{
    return $this->belongsToMany(User::class, 'conversation_participants', 'user_id', 'conversation_id');
}

in the Conversation::class but Conversation::with('participants')->get() gets me all Conversation even those the user isn't participating in.

I'm really confused atm :/

Add the following in your User model:

public function conversations() {
    return $this->belongsToMany(Conversation::class, 'conversation_participants', 'users_id', 'conversations_id');
}

And this to your Conversation model:

public function participants() {
    return $this->belongsToMany(User::class, 'conversation_participants', 'conversation_id', 'users_id');
}

If you want to link your tables easier, read up on conventions.

To get all the conversations a user is participating in, run the following (assuming you've loaded the user): $user->conversations() to get all the conversations a user is in.

If you want all users, with all their conversations, with all the participants connected, do the following: $users = Users::with('conversations.participants')->get(). You can now loop through this as follows:

foreach($users as $user) {
    foreach($user->conversations as $conversation) { 
        foreach($conversations->participants as $participant) {
            // do fancy stuff here
        }
    }
}

Notice that the user from which you start is also a participant, so maybe you need to filter that one out again.

If you want to get even more fancy (but use more resources) you could even query all the messages a conversation has too!

User::with('conversations.participants', 'conversations.messages.user')->get()

But this only works when you set up a second set of relationships along the upper table in your image (conversations <-> messages <-> users)

Edit

In the comments, OP asked if it was possible to limit the amount of messages retrieved from the database, which is possible to my knowledge, but I don't now if this is the best way:

Remove the messages from the first eager loading part:

User::with('conversations.participants')

After that, when looping through the conversations, lazy load the messages:

$conversation->load(['messages' => function($query){
    $query->take(5);
}, 'users']);

Access them after that with $conversation->messages.

Note

I think this could be done more easily in one go, but I don't have a setup right now to test this for you.

Edit 2

After Ronon added another comment, here's what I came up with:

Add a new relationship in the Conversation model:

public function last_messages() {
    return $this->hasMany(Message::class, 'conversation_id', 'id')->latest()->limit(2);
}

Because of that, you now can do this:

User::with('conversations.participants', 'conversations.last_messages.users')->get()

If you still want all the messages, you can use the messages relationship. If you want less, use the last_messages one.

Calling User::with('conversations')->get() does not specify a User. I might be misreading but I think you are looking for something like the following:

$user = User::with('conversations')->find(1);
$userConversations = $user->conversations;

which will provide you with a user and their conversations.