Reputation: 511
I've made by the book, roles for my laravel program. Problem occurs in one particular instance, one of methods in User model always "pop-up" ... Whatever user have for role_id, method always shows certain role's name, in this case "moderator". Don't know what is wrong with it, or at least i can't see it ...
Here is User model:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',"avatar"
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function rola(){
return $this->belongsTo("App\Roles", "id");
}
public function posts(){
return $this->hasMany("App\Post");
}
public function comments(){
return $this->hasMany("App\Comment");
}
public function isAdmin()
{//dd($user);
return $this->rola()->where('role', 'administrator');
}
public function isModerator()
{//dd($user);
return $this->rola()->where('role', 'moderator');
}
public function isUser()
{//dd($user);
return $this->rola()->where('role', 'user');
}
public function isPeon()
{//dd($user);
return $this->rola()->where('role', 'peon');
}
}
Here is Roles model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Roles extends Model
{
public function rola(){
return $this->hasMany("App\User", "role_id");
}
}
And for example if just display in any view:
{{auth()->user()->rola->id}} <br> // 2 <- correct
{{auth()->user()->role_id}} // 3 <- this should be 2 also.
Here is a image of my db schema:
By default, whenever new user get registered, it automatically receives role of "peon" which has id 4. Not sure where my mistake lies, maybe i'm not seeing something ...
Edit1:
Here is a link to github repo for those who want to take a gander at it.
Upvotes: 1
Views: 1945
Reputation: 2602
To improve your application, don't use one function for each role you have.
Supposed you have 100 roles on roles table, with the current code, you will also need 100 functions like isAdmin
or isSomething
.
Add something like this:
public function hasRole($roleName)
{
return $this->rola()->where('role', $roleName);
}
/**
* Check if the user has any of the given roles.
*/
public function hasAnyRole(array $roleNames)
{
$userRole = $this->rola;
return in_array($userRole->name, $roleNames);
}
Now you can check for roles:
$user->hasRole('admin'); //If the user has the admin role, returns true. Otherwise returns false.
To check for roles on blade view:
@if(Auth::check())
@if(Auth::user()->hasRole('role-name') || Auth::user()->hasRoles('another-role-name'))
//Your markup here
@endif
@endif
And for multiple roles:
@if(Auth::check())
@if(Auth::user()->hasAnyRoles(['role-name', 'another-role-name']))
//Your markup here
@endif
@endif
Hope it helps.
Upvotes: 3
Reputation: 2602
The problem is in your rola()
function.
You are using the wrong foreign key with the belongsTo
. It should be role_id
, not id
(which it currently is).
Here is a code snippet with some improvements:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',"avatar"
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function rola(){
return $this->belongsTo("App\Roles", "role_id");
//Or just return $this->belongsTo(Roles::class);
}
public function posts(){
return $this->hasMany("App\Post");
}
public function comments(){
return $this->hasMany("App\Comment");
}
public function isAdmin()
{//dd($user);
return $this->hasRole('admin');
}
public function isModerator()
{//dd($user);
return $this->hasRole('moderator');
}
public function isUser()
{//dd($user);
return
return $this->hasRole('user');
}
public function isPeon()
{//dd($user);
return $this->hasRole('peon');
}
public function hasRole($role)
{
return $this->rola->role === $role;
}
}
I suggest you to rename your rola
function within Roles model to users
, since it return all users who has some role.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Roles extends Model
{
public function users(){
return $this->hasMany(User::class, 'role_id');
}
}
One more thing: take a look at this package. It really helps you to works with users, permissions and permission groups.
Hope it helps.
Upvotes: 0
Reputation: 338
Well, I think the problem is in your rola()
function in your User.php file: you are defining a foreign key to the belongsTo
relationship which here is id
.
It should be role_id
as this is the key Eloquent would try to map to the id
of the Roles' model. See the documentation for more informations
Upvotes: 3