Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jrdavidson's avatar

Users Roles and Filters

I'm trying to figure out how to work with filters for the following situation.

Lets say I have 3 different resources being handled as controllers such as the UsersController, GraphsController, MessagesController.

I also have 4 types of roles for users. These are: basic user, editor, administrator, site owner. A user can only have 1 type of role at any given time. I've made the relationships in my models correctly. I will include the tables included below.

Lets say all users can access the messages controller and only the site owner can access the graphs controller and only the site owner and administrator can access the users controller.

How could I take care of this in the filter the easiest based on the user's role.

Table: users

id   name    role_id
1   User 1     1
2    User 2    4
3    User 3    2
Table: roles

id   role_name
1     Basic User
2    Editor
3    Administrator
4    Site Owner
0 likes
10 replies
bluesheep's avatar

One way is to use a before filter on your controllers / resources.

->before('role:Administrator');

And the filter (example):

Route::filter('role', function($route, $request, $role)
{
    if (Auth::guest() or Auth::user()->role != $role)
    {
        return Redirect::to('/youshallnotpass');
    }
}
1 like
jrdavidson's avatar

Okay but what about when more than 1 type of role can access a certain controller.

bluesheep's avatar

Hmm, I think I would turn it around. A user has many roles and just one role has access.

But if you like to do it your way, I think to pass all roles is the best way: ->before('role:Administrator,Editor');

And the your filter:

Route::filter('role', function($route, $request, $role)
{
    $roles = explode(',', $role);

    foreach($roles as $role)
    {
        if (Auth::guest() or Auth::user()->role == $role)
        {
            return;
        }
    }
    return Redirect::to('/youshallnotpass');
}

Just take that as a hint. I don't know if that works. Additionally, to call Auth::guest() on every single iteration is bad too :) I just made a minimal change to the first example.

jrdavidson's avatar

I made some changes but I'm receiving this following error.

Call to a member function before() on null 
Route::resource('users', 'UsersController')->before('role:Administrator, Site Owner');


Route::filter('role', function($route, $request, $role) { if(Auth::guest() !== true) { if(!empty($role) { $roles = explode(',', $role); if(count($roles) > 0) { $truth_roles = array(); foreach($roles as $role) { if (Auth::user()->role == $role) { array_push($truth_roles, $role); } } return $truth_roles; } } return Redirect::to('/youshallnotpass'); } }
bluesheep's avatar

->before() doesn't work on resources if I'm right.

You have to set your filter within the constructor of the controller:

class UsersController extends BaseController {

    public function __construct()
    {
        $this->beforeFilter('role:Administrator, Site Owner');
    }

}

You'll find more information here: http://laravel.com/docs/4.2/controllers#controller-filters

jrdavidson's avatar

I performed the top it initially works but I"m wondering how what is being passed as the role and what not.

class BaseController extends Controller {

    public function __construct()
    {
        Auth::loginUsingId(1);
        $currentUser = User::with('role')->find(Auth::user()->id);
        echo '<pre>';
        dd($currentUser);
        echo '</pre>';
        View::share('currentUser', $currentUser);
    }
}
class UsersController extends BaseController {

    public function __construct()
    {
        $this->beforeFilter('role:Administrator, Owner');
    }
}
Route::filter('role', function($route, $request, $role)
{
    if(Auth::guest() !== true)
    {
        if(!empty($role))
        {
            $roles = explode(',', $role);
            if(count($roles) > 0)
            {
                foreach($roles as $role)
                {
                    if (Auth::user()->role == $role)
                    {
                        return;
                    }
                }
            }
        }
        return Redirect::to('/youshallnotpass');
    }
});
array(11) {
  ["id"]=>
  string(1) "1"
  ["first_name"]=>
  string(7) "John"
  ["last_name"]=>
  string(8) "Smith"
  ["username"]=>
  string(10) "jsmith"
  ["email_address"]=>
  string(20) "jsmith@gmail.com"
  ["role_id"]=>
  string(1) "4"
  ["status_id"]=>
  string(1) "1"
  ["created_at"]=>
  string(19) "2015-01-06 03:15:53"
  ["updated_at"]=>
  string(19) "2015-01-06 03:15:53"
  ["deleted_at"]=>
  NULL
  ["role"]=>
  array(2) {
    ["id"]=>
    string(1) "4"
    ["role_name"]=>
    string(5) "Owner"
  }
}
bluesheep's avatar

Sorry, I don't understand the question.

But now I saw a mistake I made. You have to check Auth::user()->role->role_name == $role instead. I didn't notice that at the beginning.

Maybe that was your question.

Another comment.

if(!empty($role))
 {
    //...
}

I think I would change that to and exception. Because it is wrong to set the role filter without needed roles. Or I would set a default like Route::filter('role', function($route, $request, $role = 'Site Owner')

Then the

if(count($roles) > 0)
 {
    //...
}

That is a double check for the same isn't it?

jrdavidson's avatar

Or could it be $currentUser instead of Auth::user(). Another thing is if I were to pass in the $role in the filter and dd the variable I only get Administrator so if I pass in multiple's then it doesn't show that.

Please or to participate in this conversation.