Laravel database relations - get all children from more than one parent - laravel

I have users and books.
User model:
public function books() {
return $this->hasMany('Books');
}
I can do the following:
$user = User::find(1);
$books = $user->books;
Now, I want to get all books from several users with the name Brian.
So what I did is:
$users = User::where('name', 'Brian')->get();
$books = $users->books;
Of course this does not work because books() is a method of a user and not of a group of users.
How can I can all books from all users named Brian? I could loop through all Brians but that does not seem best practice.
How could I do this?

This is the perfect spot for a whereHas call:
Give books a user relationship, then simply do:
Book::whereHas('user', function($q) {
$q->whereName('Brian');
})->get();

Related

Laravel Eloquent is there a better way to write this query?

I have a typical pivot table structure like this:
Users
id [...]
Locations
id [...]
User_Location
id | user_id | location_id
I need to get the locations the current authorized user has access to, and then I need to get all the users who also have access to all of those locations.
I tried to figure out an "eloquent" way to do this, but I'm not familiar enough with it. This works, but I'm wondering if it's the best way to do it?
$locations = auth()->user()->locations(); //returns the user_location records
$locationIds = $locations->pluck('location_id');
$locationUsers = new UserLocation();
$userIds = $locationUsers->whereIn('location_id', $locationIds)->groupBy('user_id')->pluck('user_id');
$users = User::withTrashed()
->whereIn('id', $userIds)
->get();
return view('users.index')->with('users', $users);
here's the locations() relationship referenced in the code:
public function locations()
{
return $this->belongsToMany(Location::class, 'user_location')->withPivot('primary');
}
You must create a new method in the Locations model.
public function users()
{
return $this->belongsToMany(User::class, 'user_location');
}
Then your query could look like this.
$locations = auth()->user()->locations()->with('users')->get();
$users = $locations->pluck('users');
If you need to get all users withTrashed then you should modify the first line for this.
$locations = auth()->user()->locations()->with(['users' => function ($user) {
$user->withTrashed();
}])->get();

How to if id exist from one model to another model?

I have user and playerteam model. when a certain team picks up a user for their team. Then it stores in a playerteam model like team_id and player_id.(player_id is a user_id);
now i want to show only those user who are not in playerteam model.
For that i have passed
User::with('playerTeam)->get()
in a blade file. It shows all the users but i want to show only those users whose id is not in playerteam model.
these are the code i have tried
in user model
public function playerTeam()
{
return $this->hasMany(PlayerTeam::class,'player_id');
}
Controller
$data['users'] = User::with('playerTeam')->get();
$data['playerteam'] = PlayerTeam::get();
return view('page',$data);
So, how do i show users that are not in playerteam model.
You may use doesntHave or whereDoesntHave
$data['users'] = User::whereDoesntHave('playerTeam', function ($query) {
$query->where('column', 'value');
})->get();
Or even simpler
$data['users'] = User::doesntHave('playerTeam')->get();
//...
Check docs here
You can use eloquent doesntHave method like this.
User::doesntHave('playerTeam)->get();
It will return all user which don't have a playerTeam relationship.
read docs here laravel doesntHave
$users = User::doesntHave('playerTeam')->get();
use Callback Function
use whereDoesntHave
$data['users'] = User::whereDoesntHave('playerTeam', function ($query) {
$query->where('column', 'value');
})->get();
Refer Following Link
whereDoesntHave

Laravel eloquent and query with two join tables criterias

Here the situation.
I have a user table, a role table (different users can have the same role) and a post table (different users can be linked to a same post - multi authors post). I also have two join tables that link user and role and user and post. I have built all relationships (many-to-many).
But now I try to get all users that have a particular role ('id' = 2 for example) and have contributed to a particular post ('id' = 45 for example).
I can do it with one criteria :
$roles = App\Role::where('id', 2)->first();
foreach ($roles->users as $user) {
}
But I didn't find the solution with two criterias (role id and post id).
You can use relationship existence to to achieve your goal. And the whereHas() function is for checking relationship existence.
Assuming that you have defined relationships on models
$roleId = 2;
$postId = 45;
$users = User::whereHas('role', function($query) use ($roleId) {
$query->where('id', $roleId);
})
->whereHas('post', function ($query) use ($postId) {
$query->where('id', $postId);
})
->get();

Laravel > nested eager load with restriction

Assumed we've got users, friends and restaurants. Don't want to go to deep into the Model and relationship setup.
While me as a user is logged in: How can I get all friends who are "customers" of the restaurant?
I've got this and it's already working:
$friends = array_dot(Auth::user()->friends()->select('users.id')->get());
$customers = Restaurant::with(['users' => function($query) use($friends) {
$query->whereIn('users.id', $friends);
}])->find(restaurant_id);
But is this even possible with a single query?
It sounds like you want to find all of your friends that have a relationship to the restaurant. If so, you're looking for whereHas(). General idea:
$restaurantId = 1;
$user = Auth::user();
$friendCustomers = $user->friends()->whereHas('restaurant', function ($query) use ($restaurantId) {
$query->where('id', $restaurant_id);
})->get();
You can read more about querying relations, and whereHas, here.

How to find inverse of Eloquent query

I've got a query to find enrolled students in a particular activity. On the User model:
public function enrolledStudents($activity)
{
$students = $activity->students()
->wherePivot('user_id', $this->id)
->get();
return $students;
}
Where the Activity model's students method is this:
public function students()
{
return $this->belongsToMany('Student', 'activity_student', 'activity_id', 'student_id')
->withPivot('user_id')
->withTimestamps();
}
I want another method to find the students who aren't enrolled in this activity - how could I go about this?
I.e. $user->students()->notEnrolled($activity)
Basically, you'd have to come from the Student angle. Something like this:
$students = Student::whereDoesntHave('activities', function($q) use ($activity){
$q->where('activity_id', $activity->id);
})->get();
Note that this method is quite new, so you might need to update Laravel with composer udpate

Resources