Let's say I have the relation: Role has many Users. Role and user stores a code value.
If I want to select all roles that have users with same code, how would be this query using whereHas clause?
What I tried:
$roles = Role::whereHas('users', function ($users) {
// Obviously doesn't work but it is what I need to access.
$code = $users->first()
->role
->code;
return $users->where('code', $code);
})->get();
Use this:
$roles = Role::whereHas('users', function ($query) {
$query->whereColumn('users.code', 'roles.code');
})->get();
Related
I have many to many connect with between user - cityarea.
I have also area which connect cityarea (One cityarea can connect only one area).
I have this database structure:
users
id
username
password
cityareas
id
name
area_id
cityarea_user
id
cityarea_id
user_id
areas
id
name
Next I have Models
User
public function cityareas()
{
return $this->belongsToMany('App\Cityarea');
}
Cityarea
public function area()
{
return $this->belongsTo('App\Area');
}
public function users()
{
return $this->belongsToMany('\App\User');
}
Area
public function cityareas()
{
return $this->hasMany('App\Cityarea');
}
QUESTION:
How I can get all users where areas.name = "South" with Eloquent ?
Thanks!!
By using whereHas, you can do:
$users = User::whereHas('cityareas.area', function ($query) {
$query->where('name', 'South');
})->get();
Jeune Guerrier solution is perfect, but you can use with() method of eloquent If you also need cityarea collection along with users collection.
$users = User::with('cityareas')->whereHas('cityareas.area', function ($query) {
$query->where('name', 'South');
})->get();
This is exactly what the belongs to many relationships is built for.
You simply have to do, Cityarea::where('name', 'South')->first()->users;
If you want to do something further with the query, e.g. sort by users created at, you can do
Cityarea::where('name', 'South')->first()->users()->orderBy('creaated_at', desc')->get();
Note that if there is no such Cityarea with name 'South', the ->first() query above will return null and therefore will fail to fetch the users.
A more performant way to do it programmatically is to use the whereHas approach as discussed in the comments below.
I have table for admin user and its roles with their relations. I want admin user listing with their respective role.
I tried below query
$adminusers = Admin::whereHas('roles', function($q)
{
$q->where('roles.name', '<>', 'Superadmin');
$q->select('roles.name as roles');
})->select('id', 'name')->where('admins.status', 'A')->where('admins.is_delete', '0')->paginate(15);
but i am not able to retrieve role name from it.
So how can i get the role name from above query?
You can't select from a whereHas closure. whereHas in this scenario is used to limit the results of admins, not to retrieve the roles.
You can query a relationship of a specific model like so:
$singleAdmin->roles()->where('roles.name', '<>', 'Superadmin')->get();
Or you can put constraints during eager loading:
Admin:::with(['roles' => function ($query) {
$q->where('roles.name', '<>', 'Superadmin');
}])->get();
https://laravel.com/docs/5.4/eloquent-relationships#constraining-eager-loads
Once eager loaded, you would need to access the collection of roles from $singleAdmin->roles.
In some cases, it makes sense to just use a join.
You can use the leftJoin method.
`$admins = Admin::leftJoin('roles','admin.role_id','=','roles.id')
->select('id', 'name')
->where('admins.status', 'A')
->where('admins.is_delete', '0')
->paginate(15)`
Or you can do it in model file
`public function role()
{
return $this->hasOne(\App\Models\Roles::class, 'id', 'role_id');
}`
In my application, I have setup a User model that can have subscribers and subscriptions through a pivot table called subscriptions.
public function subscribers()
{
return $this->belongsToMany('Forum\User', 'subscriptions', 'subscription_id', 'subscriber_id');
}
public function subscriptions()
{
return $this->belongsToMany('Forum\User', 'subscriptions', 'subscriber_id', 'subscription_id');
}
My question is, what relationship should I use to get a list of paginated Post models (belong to a User) from the User's subscriptions?
You can use the whereHas method to filter based on relationships. Assuming your Post model has a user relationship defined, your code would look something like:
// target user
$user = \App\User::first();
$userId = $user->id;
// get all of the posts that belong to users that have your target user as a subscriber
\App\Post::whereHas('user.subscribers', function ($query) use ($userId) {
return $query->where('id', $userId);
})->paginate(10);
You can read more about querying relationship existence in the documentation.
You can do something like this
\App\Post::with(['subscriptions' => function ($query) {
$query->where('date', 'like', '%date%');
}])->paginate(15);
Or without any conditions
\App\Post::with('subscriptions')->paginate(15);
I'm querying a table, which finds all tasks assigned to a given user (the one signed in).
I have a pivot table for the tasks/users relation, as more than one user can be assigned to a task. The function below successfully grabs all the tasks the user is assigned too. No issue there.
However, I also want to include tasks that NO users have been assigned to in the function below (in my platform, no users assigned to a task means it's for "everyone").
$user_tasks = Team::currentTeam()->tasks()->with('user', 'comments')->whereHas('user', function($query) {
$query->where('user_id', Auth::user()->id);
})->get();
Probably something like this should work:
$user_tasks = Team::currentTeam()->tasks()->with('user', 'comments')->whereHas('user', function($query) {
$query->where('user_id', Auth::user()->id);
})->doesntHave('user','or')->get();
because there is no function orDoesntHave. There's only:
public function doesntHave($relation, $boolean = 'and', Closure $callback = null)
{
return $this->has($relation, '<', 1, $boolean, $callback);
}
defined, so you need to use doesntHave and specify operator as 2nd argument.
You can get the unassigned tasks separately:
$unassigned_tasks = Task::unassigned()->get(); // Uses a scope that says where user_id is null
And then something like:
$user_tasks->tasks->push($unassigned_tasks);
In my Laravel app, I have the concept of users, friends, and groups. A user can create and sort friends into groups.
A user can have many friends:
function friendsOfMine()
{
return $this->belongsToMany('App\User', 'helpers', 'user_id', 'helper_id')
->wherePivot('accepted', '=', 1);
}
A group can have many users:
public function groupMembers()
{
return $this->belongstoMany('App\User')->withTimestamps();
}
In the UI for adding friends to a group, I want to show the full list of a user's friends, but exclude those friends that have already been added to the group. My Groups Controller function looks like this, though I'm positive I'm off-base.
public function add($id)
{
$group = Group::findOrFail($id);
$helpers = $group->groupMembers;
$id = $helpers->lists('id');
$invitees = $this->user
->friendsOfMine()
->where('helper_id', '!=', $id)
->Paginate(5);
return view('groups.add', compact('group','helpers','invitees'));
}
Ideally, what I'd love is some way to write:
$helper = $group->friendsOfMine->not->groupMembers->Paginate(5);
Is there anyway to filter data using functions from two different models?
With your approach you would have to use whereNotIn() since you have an array of ids:
$id = $helpers->lists('id');
$invitees = $this->user
->friendsOfMine()
->whereNotIn('helper_id', $id)
->Paginate(5);
However you probably could something like this as well (assuming the relation group)
$invitees = $this->user
->friendsOfMine()
->whereDoesntHave('group', function($q) use ($id){
$q->where('group_id', $id); // Note that id is the group id (not the array of ids from the helper)
})
->Paginate(5);
For a nicer syntax (like in your example) you should look into Query Scopes