laravel get relationship with multiple foriegn keys - php

I have three tables
Teams
id | Name
Winners
id | user_id | league_id
team_user
team_id | user_id | league_id
What I am trying to do in my Winner.php model is create a relationship that ties a winner to a team via the user_id and league_id
So basically I can call Winner->team and it will return the Team that the Winner belongs to where the user_id and league_id all match.
I was thinking
public function team()
{
return $this->belongsTo('App\Team', 'user_id', 'league_id');
}
But that doesnt work obviously. I am scratching my head since I have all the info I need to get the team associate to that league_id and user_id.

if your winner model returns multiple team use below code:
public function teams()
{
return $this->belongsToMany('App\Team', 'user_id', 'league_id');
}
if your winner model returns only one team use below code:
public function team()
{
return $this->belongsTo('App\Team', 'user_id', 'league_id');
}
Note:Here 3rd parameter in belogsTo() specifying your parent table's custom key

You can attach additional where() clause:
public function team()
{
return $this->belongsTo('App\Team', 'user_id', 'user_id')->where('league_id', $this->league_id);
}
Note: This will work with lazy loading only. Look here, it may help you.

I just used this as a function and not a relationship and looped through in my controller. not the best but all I got to work:
Winner.php
public function team()
{
$team_id = DB::table('team_user')
->where('league_id', $this->league_id )
->where('user_id', $this->user_id )
->first()
->team_id;
$team = Team::find( $team_id );
return $team;
}
In my controller
foreach( $league->winners as $winner)
{
$winner['team'] = $winner->team();
}

Related

Laravel: How can I get my friend relationship in a Pivot belongsToMany relation

I want to create a friendship relationship with another user in Laravel and when fetching the relationship, I want to get the user that isnt myself. (either user_id or friend_id)
This is the relationship I have:
return $this->belongsToMany(User::class, 'friend_user', 'user_id', 'friend_id')
->where('user_id', $this->id)
->orWhere('friend_id', $this->id);
When I am the user_id, I get the friend related
foreach($user->friends as $friend) {
echo $friend->first_name;
}
But when I am the friend, I get my own name. How can I solve this?
Thanks
You need two relations like below.
public function friends()
{
return $this->belongsToMany(User::class, 'friend_user', 'user_id', 'friend_id');
}
public function isFriendsWith()
{
return $this->belongsToMany(User::class, 'friend_user', 'friend_id', 'user_id');
}
Say a user with id 1 has two entries in the friend_user table like
id
user_id
friend_id
1
1
5
2
1
2
Then you can query relations like
$user1 = User::findOrFail(1);
$user1->friends; //Will get two users with an id of 2 and 5
$user2 = User::findOrFail(2);
$user2->isFriendsWith; //Will get one user with an id of 1
$user2->friends; //Will return empty collection
$user5 = User::findOrFail(5);
$user5->isFriendsWith; //Will get one user with an id of 1
$user5->friends; //Will return empty collection

show data from 2 tables laravel 6

I have a problem showing data from 2 tables with an id, in laravel 6. My tables are "users" and "companies".
users
id
name
last name
companies
id
company
address
id_user
Model user
public function company()
{
return $this->hasOne('App\Company','id_user','id');
}
Model company
public function user()
{
return $this->belongsTo('App\User');
}
Controller
public function show($id)
{
$companies = Company::with('user')->find($id);
return view('clients.show', compact('companies'));
}
view
$companies->company
but the problem is that is not showing data from users table, can someone help me?
The foreign key name for user in companies table should be 'user_id' not 'id_user'
If you want to use custom column name make sure you pass it to the second argument of the relationship.
Model company:
public function user()
{
return $this->belongsTo('App\User', 'id_user');
}

How to get all the people in table 1 without getting the people who have me as parent_id in table 2?

I'm writing this post because I have a problem with my relationships on Laravel.
Here is the structure I currently have:
1st table:
- id
- name
- ...
2nd table :
- parent_id
- child_id
knowing that parent_id and child_id correspond to the same table. Here is the function that links them
public function relation()
{
return $this->belongsToMany('App\Person', 'person_relations', 'parent_id', 'child_id', 'id', 'id');
}
Currently I would like, for a search system, to get all the people in table 1 without getting the people who have me as parent_id in table 2.
I have added an inverse relation parents() to the People model instead of the relation() method in the question.
Person Model :
public function parents()
{
return $this->belongsToMany('App\Models\Person', 'person_relations', 'child_id', 'parent_id', 'id', 'id');
}
Controller :
public function test()
{
$myId = 1;
$persons = \App\Models\Person::whereDoesntHave('parents')
->orWhereHas('parents', function($qry) use($myId){
$qry->where('person_relations.parent_id', '!=', $myId);
})
->get();
}
This method will return all records which doesn't have a given $myId as their parent id.
Tested and working in Laravel 6.2 and 7.29

Retrieving distinct relationships of relationships using Eloquent in Laravel

Lets assume I have a model for: Race, Participant, Team
And these relations: Race 1-N Participant N-1 Team
See in another way :
races 1 - N participants
teams 1 - N participants
In Laravel terms:
/* Inside Race model */
public function participants()
{
return $this->hasMany(Participant::class);
}
/* Inside Team model */
public function participants()
{
return $this->hasMany(Participant::class);
}
/* Inside Participant model */
public function race()
{
return $this->belongsTo(Race::class);
}
public function team()
{
return $this->belongsTo(Team::class);
}
In the participants table, It looks like this:
id | team_id | race_id | [a lot of other columns...]
------------------------------
1 | 1 | 1 |
2 | 1 | 1 |
3 | 2 | 1 |
4 | 2 | 1 |
In the above example, I know that the race ID 1 has 2 teams.
I can count them by doing this:
$race = Race::find(1);
$number = $race->participants()->distinct()->count('team_id');
The problem
Counting the number of teams is cool, but I want to access to the list of corresponding Team model instances, so that I can use them for further operations (within a foreach loop for example).
I tried a lot of things without success.
Something like this:
$teams = $race->participants()->distinct()->[...] // Don't know what to put here
The working equivalent SQL query is:
SELECT teams.* FROM teams
INNER JOIN participants ON participants.team_id = teams.id
INNER JOIN races ON races.id = participants.race_id
WHERE races.id = 1
GROUP BY teams.id
Resulting in this:
When the participants table contains this:
I want to know if I can do it with Eloquent instead of using Query/Builder DB:: methods directly ?
EDIT 1
My closest result:
$race->participants()->distinct()->get('team_id')
And then using this list of team_id I can access to the teams using Team::find([list of IDs]) but it looks greedy to me.
EDIT 2
I forgot some information:
The participants.team_id column is NULLABLE because:
There are races with teams of participants
There are races with participants (without team)
I don't think you can easily access to it through the $race instance.
But, you can use the whereHas method on the Team model:
$race = Race::find(1);
$teams = Team::whereHas('participants', function ($query) use ($race) {
$query->where('race_id', $race->id);
})->get(); // ->count() also works
See documentation
To get distinct teams from a race model, you could add a many to many relationship between Race and Team with Participant acting as the pivot.
For example,
/* Race */
public function teams()
{
return $this->belongsToMany(Team::class, 'participants', 'race_id', 'team_id');
}
/* Team */
public function races()
{
return $this->belongsToMany(Race::class,'participants', 'team_id', 'race_id');
}
Then, you could just do this
$race = Race::find($id);
$teams = $race->teams()->distinct()->get();
to get a list of distinct teams for the race.
And since we set up the relationship on both models, you can now also get distinct races for each team by doing
$team = Team::find($id);
$teams = $team->races()->distinct()->get();
First, let's improve your eloquent relations.
// Race
public function teams()
{
return $this->hasMany(Team::class);
}
public function withoutTeamParticipants() // change name that suits you
{
return $this->hasMany(Participant::class);
}
// Team
public function participants()
{
return $this->hasMany(Participant::class); // In this case make sure that participant.race_id is null
}
// Participant
public function team()
{
return $this->belongsTo(Team::class); // When no team, then participant.team_id is null
}
public function race()
{
return $this->belongsTo(Race::class);
}
To access list of participants of a given race:
$race = Race::where('id', 1)->with('teams.participants', 'withoutTeamParticipants')->get();
In your blade you can further use this as:
// List of participants without a team
#foreach ($race->withoutTeamParticipants as $participant)
{{ $participant->name }}
#endforeach
// List of participants that are with a team
#foreach ($race->teams as $team)
#foreach ($team->participants as $participant)
{{ $participant->name }}
#endforeach
#endforeach
You can directly use hasManyThrough relationship inside Race model for fetching distinct teams associated with the race.
public function distinctTeams()
{
return $this->hasManyThrough(Team::class, Participant::class, 'race_id', 'id', 'id', 'team_id')->distinct();
}
Now, you can loop over the teams of a race by using $race->distinctTeams
Hopefully this helps.

Laravel Eloquent Relationship custom query

I have 2 tables: USERS and SUBJECTS
The relationship between USER and SUBJECT is many to many.
In the User.php and Subject.php models, I defined:
User.php
function subjects() { return $this->belongsToMany('App\User'); }
Subject.php
function users() { return $this->belongsToMany('App\Subject'); }
The pivot table is subject_user and it has 3 columns:
subject_id, user_id, finished
The finished value can only be between 0 and 1.
Now I know that when I want to select all the subjects that an user studied, I have to write $user->subjects.
But what if I want to select all the subjects that an user studied and the finished value in the pivot table is equal to 1?
You need to add "withPivot()" to your relationship definitions, like this:
function subjects() { return $this->belongsToMany('App\User')->withPivot('finished'); }
function users() { return $this->belongsToMany('App\Subject')->withPivot('finished'); }
Then you can do:
$user->subjects()->where('finished', 1)->get();
You will need to eager load that relationship and use the wherePivot method.
$user = User::with(['subjects' => function($q) {
$q->wherePivot('finished', 1);
}])->fine($user_id);

Categories