Get user that belongs to a specific role in laravel - laravel

I have following table for roles:
id | name | user_id
1 Admin NULL
2 Accountant 1
3 Storekeeper 1
and user table like this:
id | name | role_id
1 Admin 1
2 xyz 2
3 xyz 3
I want to retrieve all data from users table that have been created by Admin in my case that have user_id 1.
I'm using this relation:
public function Role()
{
return $this->hasMany('App\Models\Role', 'user_id', 'id');
}
$users = User::with('Role')->whereHas('Role', function($query) {
$query->where('user_id', 1);
})->get();
but this is not returning data from users table it is returning rows from roles table only that have user_id 1.
larar

From your database structure, the relation user to role is belongsTo not hasMany
each user has one role.
each role can be assigned to many users.
User ==Belongs to==> Role
Role ==Has many==> User
public function role()
{
return $this->belongsTo('App\Models\Role', 'role_id', 'id');
}
And then you call the users with admin role like this.
$adminsWithRole = User::with('role')->whereHas('Role', function($query) {
$query->where('roles.id', 1);
})->get();
Lets say you want to get the Created roles by the users that are admin
This needs its own relation
public function createdRoles()
{
return $this->hasMany('App\Models\Role', 'user_id', 'id');
}
The get the created roles by all users that have the role admin
$adminsWithCreatedRoles = User::with('createdRoles')->whereHas('Role', function($query) {
$query->where('roles.id', 1);
})->get();

Related

Fetch data that don't exist in pivot table column - Laravel 6

I have two tables viz
1. users
columns: id, name
2. user_access
columns: id, user_id, user_access_id
user access is a pivot table that defines the relationship between users table and users table itself. For example, a user might have access to data of some other users.
I have defined this relationship in User model.
Now I want to fetch those user ids for a user which don't exist in user_access table.
For example, a user may have access to id 1 & 2 but he doesn't have access to id 3 & 4, so I want to fetch id 3 & 4 and not 1 & 2.
To achieve this I use whereDoesntHave eloquent but it's not working for relationship on the same tables and I get the following error
Facade\Ignition\Exceptions\ViewException
Call to undefined method Illuminate\Database\Eloquent\Builder::getRelated() (View: C:\xampp\htdocs\prd_tracker\resources\views\tracker\ticket\script.blade.php)
but it does work for different tables.
Here is my code
User Model
public function userAccess()
{
return $this->belongsToMany('App\User', 'user_access', 'user_id', 'user_access_id')->using('App\USER_ACCESS');
}
Logic
use App\User;
$user_id = Auth::user()->id;
//Get All Those Users Ids Which Does Not Belong To Auth User
$exception_user_ids = User::whereDoesntHave('users', function ($query) use($user_id) {
$query->where('user_id', $user_id);
})
->pluck('id');
The error may be in the User model.
The App\User model cannot belongsToMany() of itself...App\User.
I believe you may need a UserAccess model.
Try:
User Model
public function userAccess()
{
return $this->belongsToMany('App\UserAccess', 'user_access', 'user_id', 'user_access_id')
}
or try a hasMany relationship:
User Model
public function userAccess()
{
return $this->hasMany('App\UserAccess', 'user_id', 'id');
}
https://laravel.com/docs/7.x/eloquent-relationships#many-to-many
https://laravel.com/docs/7.x/eloquent-relationships#one-to-many

laravel: How to get column related to another column in pivot table (3 column pivot)

I'm not sure how to phrase this question, but I need to do the following:
I have a pivot table with three columns user_id, account_id, role_id
So in my database if I have these rows on account_role_user (pivot)
|---------------------|------------------|-------------
| account_id | user_id | role_id |
|---------------------|------------------|-------------
| 1 | 1 | 1 |
|---------------------|--------------------------------
| 2 | 2 | 1 |
------------------------------------------------------
| 1 | 2 | 3 |
------------------------------------------------------
Role - 1 = owner
Role - 3 = manager
What I'm trying to do is get users on a specific account with their specific role. But I'm only able to query things like App\User::with('accounts.roles')->whereId(2)->first(); which does show the users on an account, but it groups their roles that aren't specific to the account.
I only want the users and their roles that are relevant to the account.
If I'm querying account with id of 1 and I want to list users on that account with their role, I should have something like:
$account = App\Account::find(1)
User with ID of 1 has a role id of 1 on the account id of 1
User with ID of 2 has a role id of 3 on the account id of 1
User Model:
public function accounts() {
return $this->belongsToMany('App\Account', 'account_role_user', 'user_id', 'account_id');
}
public function roles() {
return $this->belongsToMany('App\Role', 'account_role_user', 'user_id', 'role_id');
}
Account model:
public function users() {
return $this->belongsToMany('App\User', 'account_role_user', 'account_id', 'user_id');
}
public function roles() {
return $this->belongsToMany('App\Role', 'account_role_user', 'account_id', 'role_id');
}
Role Model:
public function users() {
return $this->belongsToMany('App\User', 'account_role_user', 'role_id', 'user_id');
}
public function accounts() {
return $this->belongsToMany('App\Account', 'account_role_user', 'role_id', 'account_id');
}
Thanks to someone's help on Laravel's Discord channel, I figured this out.
On the Account Model, I changed the users() relation to:
public function users() {
return $this->belongsToMany('App\User', 'account_role_user')
->using('App\AccountRoleUser')
->withPivot('role_id');
}
I created a pivot model called AccountRoleUser
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class AccountRoleUser extends Pivot
{
public function role() {
return $this->belongsTo('App\Role');
}
}
And on the User model, I changed the accounts() relation to:
public function accounts() {
return $this->belongsToMany(Account::class, 'account_role_user')->withPivot('role_id');
}
Now my query is really succinct and logical:
$account = auth()->user()->accounts->where('foo', 'bar')->first();
$users = $account->users;
Each User inside the collection has a pivot object now coming from the pivot model.
Which means I can now do something like:
#foreach ($users as $user)
<p>This is user {{ $user->first_name }} {{ $user->last_name }} with a role of
{{$user->pivot->role->description}}
</p>
#endforeach

Issue with eloquent an relashionship many to many in laravel 6.0

I started to learn laravel 1 month ago and I have the next issue.
I have 2 models, user and role and they have M to N relationship, therefore I have 3 tables.
Class Role Class Role_User Class User
=========== =============== ===========
id | name id | user_id | role_id id | name | lastname
1 ADMIN 1 1 1 1 John Rambo
2 AUTOR 2 1 2
3 USER
In the models I have the next code
Model User
public function roles()
{
return $this->belongsToMany(Role::class, 'role_user');
}
Model Role
public function users()
{
return $this->belongsToMany(User::class);
}
I need in my view to list all user with role ADMIN and I dont know waht code I need to put.
public function index($type)
{
$users = Role::all()->roles()->where('name', 'ADMIN');
return view('admin.user.list', compact('users'));
}
Could you help me pls?
Since you want a result composed of users, you need to launch your query on them. And dont forget to run the query with get() (this case), first(), find(..)....
$users = User::whereHas('roles', function ($role) {
$role->where('name','ADMIN');
})->get();
return view('admin.user.list', compact('users'));

Laravel: how order by many to many table?

I have tables
users
id
username
role
id
name
users_role
user_id
role_id
I have users listing and I want ability to sort by username and role_id, how I can do this?
users
1:first
2:second
3:third
roles
1:admin
2:customer
users_role
1:1
1:2
2:2
3:2
Sort can be by first user role_id(or for max role_id -> if user have roles 1 and 2 sort by 2)
First of all, you need to create relationships for two model: User and Role (i suppose that we have three tables: users, roles and role_user:
class User extends Model
{
public function roles() {
return $this->belongsToMany('\App\Role');
}
}
class Role extends Model
{
public function users()
{
return $this->belongsToMany('\App\User');
}
}
Next, with this query you can have list of users and roles, sort by username ASC and role_id DESC
\App\User::with(array('roles' => function($query) {
$query->orderBy('role_id', 'DESC');
}))
->orderBy('username', 'ASC')
->get();

Eloquent Many to Many select User without certain Roles

So I have User & Role models with many-to-many relationship, I have 3 roles: super, admin and moderator with 4 users let's says: John, Mike, James and Larry.
John is a super, Mike has admin and moderator roles, James is an admin and Larry is a moderator. To displaying users who doesn't have certain roles I created this scope:
public function scopeDoesntHaveRoles($query, $roles = [], $column = 'id') {
return $query->whereDoesntHave('roles')->orWhereHas('roles', function ($q) use ($roles, $column) {
$q->whereNotIn($column, $roles);
});
}
When I call User::doesntHaveRoles([1])->lists('name', 'id') to get users who doesn't have super role, it works and returns:
{"2":"Mike","3":"James","4":"Larry"}
But, when I trying to list users who doesn't have admin role User::doesntHaveRoles([2])->lists('name', 'id'), yes James is not shown there but Mike is appeared while he is actually has admin role:
{"1":"John","2":"Mike","4":"Larry"}
I think it's because Mike is also has moderator role, do you see something wrong in my scope? or do you have other solutions?
Thanks
Edit:
Here is my pivot schema
Schema::create('user_roles', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->primary([
'user_id', 'role_id'
]);
});
User model
public function roles()
{
return $this->belongsToMany(Role::class, 'user_roles');
}
Role Model
public function users()
{
return $this->belongsToMany(User::class, 'user_roles');
}
I would use whereNotIn instead of whereDoesntHave.
Given a Role stored in the variable $role you can get all users who don't have that role with:
/* #var Role $role */
User::whereNotIn(function('id', $query) use ($role) {
$query->select('user_id')
->from('user_roles')
->where('role_id', $role->id);
});
The inner query will return all IDs of users who has the given role. Using whereNotIn will return the opposite set of users. The folowing query will be created:
select *
from users
where user_id not in (
select user_id
from user_roles
where role_id = ?
);
Now having a Collection of roles stored in $roles you can get all users who don't have any of that roles with:
/* #var Collection|Role[] $roles */
User::whereNotIn(function('id', $query) use ($roles) {
$query->select('user_id')
->from('user_roles')
->whereIn('role_id', $roles->pluck('id');
});
The inner select will return IDs of all users who has one of the roles in the collection. With whereNotIn you will again get the opposite result. You can also use an array of role-ids instead of $roles->pluck('id').
The builder will create a query like
select *
from users
where user_id not in (
select user_id
from user_roles
where role_id in (?, ?, ..)
);

Resources