rose
rose

Reputation: 197

Using Middleware to Obtain Admin Permissions

When I try to write an admin rule to prevent users to enter certain route I get this error: Property [name] does not exist on this collection instance.

User Model

<?php

public function roles()
{
    return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');
}

public function isAdmin()
{
    if ($this->roles->name == "Admin") {
        return true;
    }
    return false;
}

Admin Middleware

public function handle($request, Closure $next) 
{

   if (Auth::check()) {
       if (Auth::user()->isAdmin()) {
       return $next($request);
       }
    }
    return redirect('/');
 }

Routes and Controller

Route::group(['middleware' => 'admin'], function () 
{ 
    Route::get('/home', 'HomeController@index')->name('home');
});

public function __construct()
{ 
    $this->middleware('admin');  
}

Upvotes: 0

Views: 65

Answers (2)

Tharaka Dilshan
Tharaka Dilshan

Reputation: 4499

$this->roles returns a Collection instance. so you can't access a property from a collection. That is the error.

In this scenario You only need to know that this user is an admin or not. So you don't have to fetch all the roles to do that. And doing that is less efficient too.

So the best solution is use exists() function.

public function isAdmin()
{
    // is there a role which name is admin.
    if ($this->roles()->where('name', 'Admin')->exists()) {
        return true;
    }
    return false;
}

Upvotes: 2

newUserName02
newUserName02

Reputation: 1678

The roles() relationship on the model is for many-to-many, so calling $this->roles returns a collection of models, not a single model instance. If you want to check if Admin is one of the roles that the current user has, try something like this:

public function isAdmin()
{
    if ($this->roles->pluck('name')->contains('Admin')) {
        return true;
    }
    return false;
}

The pluck() method returns a "column" of data from your collection (in this case the name field) as a new collection. The contains() method searches the collection for the given value, and returns true if the collection contains the value, or false if it does not.

https://laravel.com/docs/5.7/collections#available-methods

Upvotes: 2

Related Questions