George G
George G

Reputation: 93

Laravel 7: Connect 3 tables using models

I have three different tables:

Team_Action has a FK (action_id) with Perimissions which I need the name value of that table. Team_Action also has a FK (user_id) with Users which I need the name value of the users table.

At the time, I can only access ID's and not names.

I was wondering if there is any way to achieve the following by only using Laravel's models:

@foreach($team->teamAction as $tmdata)
<tr>
  <td>
    $team->teamMember->name
  </td>
  <td>
   $team->teamAction->name
  </td>
</tr>
@endforeach

my Team model:

    //Infinite users belong to a team
public function teamMembers() {
    return $this->hasMany(TeamsMembers::class,'team_id','id');
}

    //Infinite actions per team
public function teamAction(){
    return $this->hasMany(TeamsAction::class);
}

TeamAction

    public function team(){
    return $this->belongsTo(Team::class);
}

Permission

public function teamAction(){
return $this->belongsTo(TeamsAction::class,'action_id');}

TeamsMembers

    public function team() {
    return $this->belongsTo(Team::class,'team_id','id');
}
public function teamMember(){
    return $this->hasMany(User::class,'id','user_id');
}

My controllers code:

$teamID = $request->route('id');
$team = Team::where('id',$teamID)->get()->first();
        

        foreach ($team->teamAction as $tta) {
            $allTeamActions = Permission::where('id', $tta->action_id)->get();
        }

        foreach ($team->teamMembers as $ttm){
            $allTeamMembers = User::where('id', $ttm->user_id)->get();
        }

I am aiming for something like this

$allTeamActions = Permission::where('id', $team->teamAction[0]->action_id->name)->get();

EDIT: Let me put on some visuals to make it more clear: enter image description here

Is there a way to retrieve through eloquent models the name values which are FK's of those models to the model I am using? 1

The scenario is the following: Each member belongs to a Team. (Table Teams: ID, creator_id) The team has multiple members in another table named team_members (user_id, team_id). A team has multiple actions stored in another table named team_actions which store FK values coming from another table named permissions (team_id,action_id_user_id). A user table stores all the actual information of the users (aka their names which I'd like to use)

I want to create a view table with all that information. Namely, I am trying though the Teams model to access the following information: Team users (their names coming from users table, the ID of the user is stored in team_members and team_actions)

Team user actions (the name of the action coming from the permission table, the ID of the action is stored in team_actions)

Upvotes: 1

Views: 73

Answers (1)

M Khalid Junaid
M Khalid Junaid

Reputation: 64476

As per the provided description team_actions table look like a pivot or junction table which forms a many to many relation between team <-> users & team <-> permissions. Based on this conclusion you can define a hasMany() relation to team_actions table which will be a TeamMemberAction model

class TeamMemberAction extends Model
{

    protected $table = 'team_actions';

    public function member()
    {
        return $this->belongsTo(User::class, 'id', 'user_id');
    }
    public function team()
    {
        return $this->belongsTo(Team::class, 'id', 'team_id');
    }
    public function action()
    {
        return $this->belongsTo(Permission::class, 'id', 'action_id');
    }
}


class Team extends Model
{
    
    public function member_actions()
    {
        return $this->hasMany(TeamMemberAction::class, 'id', 'team_id');
    }
}

So I guess there is no need for additional team_members table just to get the team members list.

Now with this new mapping you can get the members and actions as

$team = Team:with(['member_actions.member','member_actions.action'])->find(1);

For member name you will need to loop $team->member_action collection, and each collection will have a member key with member details from user table same goes for actions like

{
    id:1
    name:"Team One"
    member_actions: [{
            id: 3,
            member: {
                id: 7
                name: "User name"
            },
            action: {
                id: 11,
                name: "Action name"
            }
        },{
            id: 5
            member: {
                id: 9,
                name: "User name"
            },
            action: {
                id: 13,
                name: "Action name"
            }
        }]
}

If you directly want the team members then you an define belongs to many relations in your team model as

class Team extends Model
{
    public function members()
    {
        return $this->belongsToMany(User::class, 'team_actions', 'team_id', 'user_id');
    }
    public function actions()
    {
        return $this->belongsToMany(Permission::class, 'team_actions', 'team_id', 'action_id');
    }

}

Then you can eager load both relations as

$team = Team:with(['members','actions'])->find(1);

{
    id:1
    name:"Team One"
    members: [{
            id: 3,
            name: "User name"
        },{
            id: 5,
            name: "User name"
    }],
    actions: [{
            id: 7,
            name: "Action name"
        },{
            id: 9,
            name: "Action name"
    }]
}

Upvotes: 1

Related Questions