laraveleloquentrelationship

Laravel relationship between 3 models (group,member,post)


I have 3 models that are related to each other.

  1. Group
  2. GroupMember
  3. GroupPost
  4. GroupPostComment

Now, I have separated the database tables as well.

  1. groups
  2. group_members
  3. group_posts
  4. group_post_comments

For each group a member is a member of, I insert a new row in group_members. The foreign key here is "group_id", which relates to the id field in groups. In group_posts there is a new row for every post posted. This container a group_id field as well.

What I'm struggling with is the GroupMember model. How can I get an collection of all the posts from this GroupMember, that the GroupMember posted in that one group its related to?

Here is my models setup.

Group model

public function category() {
    return $this -> belongsTo('App\GroupCategory', 'category_id');
}

public function owner() {
    return $this -> hasOne('App\GroupMember', 'group_id') -> where('owner', true);
}

public function mods() {
    return $this -> hasMany('App\GroupMember', 'group_id') -> where('mod', true);
}

public function admins() {
    return $this -> hasMany('App\GroupMember', 'group_id') -> where('admin', true);
}

public function members() {
    return $this -> hasMany('App\GroupMember', 'group_id');
}

public function posts() {
    return $this -> hasMany('App\GroupPost', 'group_id');
}

public function comments() {
    return $this -> hasMany('App\GroupPostComment', 'group_id');
}

GroupMember model

public function group() {
    return $this -> belongsTo('App\Group');
}

public function posts() {
    return $this -> hasMany('App\GroupPost', 'group_id', 'group_id');
}

public function comments() {
    return $this -> hasMany('App\GroupPostComment', 'group_id', 'group_id');
}

public function user() {
    return $this -> belongsTo('App\User');
}

GroupPost model

public function user() {
    return $this -> belongsTo('App\User');
}

public function comments() {
    return $this -> hasMany('App\GroupPostComment', 'post_id');
}

public function group() {
    return $this -> belongsTo('App\Group');
}

The problem is the GroupMember model and the posts() / comments() method. There is an error in my relation, but I can't see what I am doing wrong.

Does anyone see what I'm doing wrong?


Solution

  • This case is a little bit confusing to resolve, although easy to. I guess that's why you haven't received any help yet because some people struggle to understand.

    1. Clear some confusions

    In your title you mentioned

    Laravel relationship between 3 models (group,member,post)

    Yet, there is no Member model to be seen. And I think most of your difficulties come from there. In my tryout, I will assume you have a User model and the table that goes with.

    Question: Can a user be member of many groups ? If the answer is yest, then you have a many to many relationship between Group and User (members). Thus, update your Group model like this:

    public function members() {
        return $this->belongsToMany('App\User', 'group_members', 'group_id', 'member_id');
    }
    

    And in the User model, you define the opposite

    public function groups() {
        return $this->belongsToMany('App\Group', 'group_members', 'member_id', 'group_id');
    }
    

    Right, you noticed now group_members table has a composite key made of group_id and member_id respectively representing groups and users table.

    2. How to get the all the posts belonging to a member in a specific group

    First thing first, a GroupPost (post) belongs to two entities: a Group and User (member). In your GroupPost model you already have a relationship to User. So all good. To answer your questions, there are many possibilities.

    //Direct eloquent when user id and group id are known
    $posts = GroupPost::where('user_id', 1)->where('group_id', 1)->get();
    
    //Directly from the user 
    $member = User::find(1);
    $posts = $member->groupPosts()->where('group_id', 1)->get();
    

    Don't forget to define groupPosts() relationship in User model

    public function groupPosts() {
        return $this->hasMany('App\GroupPost');
    }