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

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();

Related

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

get user from belongsToMany relationships

I have a service model in October CMS.
In this model, I need to get postman's users (postman is user group) but I am receiving this error:
Trying to get property of non-object
This is my code
public function getPostmanIdOptions()
{
$groups = UserGroup::where('id','4')->lists('name', 'id');
$groups->users;
$list = [' ' => 'choose'] + $groups;
return $list;
}
At the moment, your lists() function will only return the name and the id of each user group. This is used to return thelselect options for the backend select (I am assuming).
What you need to do in this case is return the record based on its id which can be done using the find() eloquent method.
By doing this, the full UserGroup model will be returned, with it's relationships etc.
You're new code should look something like this:
...
$group = UserGroup::find(4);
$users = $group->users;
...
After retrieving the users, you can then using the lists() method if required to:
$list = $group->users->lists('name', 'id');

How to add condition in connection tables?

I have two tables: Users and Images.
So, a user can have some images.
For this relationship I have additional function in model User:
public function images()
{
return $this->hasMany('App\Images', 'idElement', 'id');
}
And in controller I have:
$users = Users::where('id', $id)->with("images")->get();
How can I add additional condition in controller for images table that will be "where images.type = 1"?
Now this tables are connected only by primary keys, but I need to set a new condition yet.
You can filter your images with callback function, try this:
$users = Users::where('id', $id)->with(["images" => function ($query){
$query->where('type', 1);
}])->get();
For something like this, where you want to scope down a subset of images based on their type, you can add another method called something like public function scopedImages() and define it as such:
public function scopedImages() {
return $this->hasMany('App\Images', 'idElement', 'id')->where("images.type", "=", 1);
}
In your controller, you would access this function the same as you would the images() function on User:
$users = Users::where('id', $id)->with(["scopedImages"])->get();
Keep the function images() as well, so if you need to find all images attached to a User, but adding additional functions like this gives you flexibility on what you want to return and when.

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

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();

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