I'm working in this Laravel project which has this structure
users: id | first_name |...
roles: id | name
assigned_roles: id | user_id | role_id
I think this is quite obvious :p
User model
class User extends ConfideUser {
use HasRole;
public function Roles(){
return $this->belongsToMany('Role','assigned_roles');
}
Role model
class Role extends EntrustRole
{
public function Users()
{
return $this->belongsToMany('User','assigned_roles');
}
}
I'm looking for a way to get all users with a specified role in this case 'Teacher'. I've tried this:
$students = User::with(array('Roles' => function($query) {
$query->where('name','Teacher');
}))
->get();
return $students;
but this always returns an array of all users.
would anyone know why that's so?
Thanks!
What you're currently asking laravel for in your $students query, is 'give me all the students, and for each student get me all of their roles if the role is teacher'
Try using the whereHas
$students = User::whereHas(
'roles', function($q){
$q->where('name', 'Teacher');
}
)->get();
This should get you the users, but only where they have a role where the name is teacher.
If you are using spatie/laravel-permission or backpack/permissionmanager you can simply do:
$teachers = User::role('Teacher')->get();
Try This.
Role::where('rolename', 'user')->first()->users()->get()
In case you want to get all users with a list of potentials roles:
$authorizedRoles = ['Teacher', 'Professor', 'Super professor'];
$users = User::whereHas('roles', static function ($query) use ($authorizedRoles) {
return $query->whereIn('name', $authorizedRoles);
})->get();
If You Are using laravel-permission package then,
In Controller,
$rolesWithUserCount = Role::withCount('users')->get();
In Blade File,
#foreach ($rolesWithUserCount as $item)
{{ $item->name }}
{{$item->users_count }}
#endforeach
OutPut:
Role1 Role1Count
Role2 Role2Count
....
For More:
VISIT: https://laravel.com/docs/7.x/eloquent-relationships#counting-related-models
Related
For example: I have these models in my application.
User, Profile, Interest.
I linked the users table with the profiles table by adding the user_id column in the profiles table. And I linked profiles and interests by using a pivot table (interest_profile), Which is (as obvious) will have two columns (profile_id, interest_id).
However, I want to query the users who are associated with a profile, too see who is associated with a particular interest, In other words: "select all users who are having (in their profiles) that particular interest".
I know that I can do this with raw SQL by joining the four tables and then use (where clause).. But I want to do it the Laravel way.
Thanks in advance.
First make sure you have your relationships setup correctly on your models like:
class User extends Model
{
public function profile()
{
return $this->hasOne(Profile::class);
}
}
class Profile extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function interests()
{
return $this->belongsToMany(Interest::class, 'interest_profile');
}
}
class Interest extends Model
{
public function profiles()
{
return $this->belongsToMany(Profile::class, 'interest_profile');
}
}
Then you can use whereHas() to constrain a query by a related model and dot notation for nested relations. So your query would be:
User::whereHas('profile.interests', function($query) use ($interestName) {
return $query->where('name', $interestName);
})->get();
That would just return a collection of users. If you wanted to return their profiles and interests as well you would use with():
User::whereHas('profile.interests', function($query) use ($interestName) {
return $query->where('name', $interestName);
})
->with('profile.interests')
->get();
Assuming the User model has a relationship profile and the Profile model has a relationship interests, you can do this.
$interest_id = 1;
$users = User::whereHas('profile', function ($query) use ($interest_id) {
$query->whereHas('interests', function ($query) use ($interest_id) {
$query->where('id', $interest_id);
});
})->get();
I'm trying to extract all companies and contacts with pivot.main_contact = 1.
Tables:
Company: id, name
Company_contacts: id, company_id, contact_id, main_contact
Contacts: id, name
Model:
class Company extends Model
{
public function mainContact()
{
return $this->belongsToMany('App\Contact', 'company_contacts')
->wherePivot('main_contact', '=', 1);
}
}
Controller:
$query = Company::with('mainContact')->get();
This returns companies + ALL contacts for the companies and NOT ONLY the ones with main_contact = 1.
First, for reasons I'm unsure of, you need to add withPivot('main_contact'); to your relation. This will return main_contact in your collection under pivot
class Company extends Model
{
public function mainContact()
{
return $this->belongsToMany('App\Contact', 'company_contacts')
->withPivot('main_contact');
}
}
The second thing you need to do is use withPivot() while constraint eager loading like so:
$companies = Company::with(['mainContact'=> function($query){
$query->wherePivot('main_contact', 1);
}])->get();
I've checked it, it works.
Just to go a bit above and beyond. Sometimes you'll want to query a pivot table without knowing the value. You can do so by:
$companies = Company::with(['mainContact'=> function($query) use ($contact){
$query->wherePivot('main_contact', $contact);
}])->get();
Try to add withPivot():
return $this->belongsToMany('App\Contact', 'company_contacts')
->withPivot('main_contact')
->wherePivot('main_contact', '=', 1);
Company::with('mainContact')->get(); returns all compaines and all contacts. You should be doing $company->mainContacts()->get(); instead.
$companies=Company::all();
foreach($companies as $company)
{
print_r($company->mainContact()->get());
}
die;
Hello I'm very new in Laravel and, I'm having the following models :
organizations
-----------------
id
name
public function users()
{
return $this->belongsToMany( 'App\User' );
}
users
-----------------
id
name
organization_user
------------------
user_id
organization_id
The there is a many to many relationship between organization and user. Now I want to find the organization where the user belongs to. How can I add a where condition for the user in the relationship.
For example I want to find all the organization of the logged in user. I'm trying the following :
$organisations = Organisation::where('user_id' , '=' , $user->id)->paginate(10);
But its not working because user_id is in my Pivot Table. Please help and Thanks in advance.
I think you need to use wherePivot() function in your code like
$organisations = Organisation::with(array('user'=> function($query) use ($user){
$query->wherePivot('user_id' , '=' , $user->id);
}) )->paginate(10);
May be this can help
I think below code may help you
$organisations = Illuminate\Support\Facades\DB::table('organizations')
->join('organization_user', 'organizations.id', '=', 'organization_user.organization_id')
->join('users', 'users.id', '=', 'organization_user.user_id')
->where('users.id', '=', $user->id)
->paginate(10);
I think you need to add this to your User Model
public function organizations()
{
return $this->belongsToMany('App\Organization');
}
and then will be something simple like this
$organizations = Auth()->user()->organizations;
First of all add your relations in your models:
User.php
public function organizations()
{
return $this->hasMany(organization_user::class);
}
Or
public function organizations()
{
return $this->hasManyThrough(organizations::class,organization_user::class);
}
I recommend the second one. For more information follow this:
Laravel hasManyThrough
Please note that use same idea for organization model to create the relation
I have the following database Structure:
users
________
id
user_fields
________
id
name
user_field_values
________
id
user_id
field_id
value
I have a basic hasMany Relation on UserFieldValues but this looks awful for me, especially because i don't want to iterate the whole Relation just to get a specific user_field_values.value on a specific user_fields.name.
So what i want to get is a user_fields_values.value from the current user where user_fields.name = ?
My idea is to make a belongsToMany Relation but I dont get it to work.
I really would appreciated your help.
Solution
Thanks to Lê Trần Tiến Trung, "load" was the keyword i was looking for.
public function userFields() {
return $this->belongsToMany('\App\Models\UserFields',"user_field_values", 'user_id', 'field_id')->withPivot('value');
}
public function userField($fieldName) {
$this->load(['userFields' => function($q) use ($fieldName) {
$q->where('slug', '=', $fieldName);
}])->first();
}
The easiest way is using belongsToMany, withPivot to get value, add where clause to select correctly relation. Here is example, not tested.
// User.php
public function fields()
{
return $this->belongsToMany('Field', 'user_field_values')->withPivot('value');
}
// query
$users = User::all();
$users->load(['fields' => function($q) use ($fieldName) {
$q->where('name', '=', $fieldName);
});
foreach ($users as $user) {
echo $user->fields->first()->pivot->value;
}
I have 4 tables:
projects: id, text
comments: id, text
comment_project: project_id, comment_id
project_group: project_id, user_id
My goal is to take all commets and user details for some project.
Currently I am able to get all comments for projects like this:
class Project extends Model {
public function comments(){
return $this->belongsToMany('App\Comment','comment_project');
}
}
and in controller I do like this:
$comments = Project::find(1)->comments()->get();
return $comments;
Any idea how to take only comments and user details for selected project if project_id and user_id exists in project_group table?
You'll need to set another relation method for project_group in your Model, then you should be able to get this like so:
$comments = Project::with(['comments','project_group'])
->whereHas('project_group',function($q){
$q->whereNotNull('user_id');
$q->whereNotNull('project_id');
});
dd($comments);
Model:
class Project extends Model {
public function comments(){
return $this->hasMany('App\Comment','comment_project');
}
public function project_group(){
return $this->hasMany('App\project_group','comment_project'); // < make sure this is the name of your model!
}
}
Try this:
$comments = Project::whereHas('groups',function($q){
$q->where('project_id',1);
})->whereHas('comments', function($q){
$q->where('user_id',Auth::id())->where('project_id',1);
})
->get();
return $comments;
Here is how I do this, if anyone has better idea pls comment...
Both methods are belongToMany()
$userCondition = function($q){
$q->where('user_id',Auth::id())->where('project_id',1);
};
$commentsCondition = function($q){
$q->where('project_id',1);
};
$comments = Project::with(['comments' => $commentsCondition,'groups' => $userCondition])
->whereHas('groups', $userCondition)
->whereHas('comments', $commentsCondition)
->get();
return $comments;