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

vincent15000's avatar

What's the best way to write a different query for each user role ?

Hello,

I work on an application where there are teams with users having different roles.

If a user wants to see some data, the query has to be different according to the role.

What's the best way to do that ?

Is it for example writing scopes ? I thought about a specific scope for each role, for example scopeFilterForManager(), so that I can have a unique bae query and then filter the datas according to the role.

Is there perhaps another way with some dynamic scopes so that I use only one scope in the query but write different scopes in the model ?

I need to customize the query but not to retrieve any data directly binded to the user role. For example if the role is super manager, he can see all, but if the role is manager, he can only see the tests for his team, ... there are some other weird rights like these ones.

Thanks for your suggestions.

Vincent

0 likes
5 replies
Pippo's avatar

Scopes can receive parameters, so you can pass the role and use it to dynamize a single scope:

public function scopeUserRole($query,  $user)
{
	switch ($user->role) {

		case 'super_manager':
			break;

		case 'manager':
			$query->where ('team_id',  $user->team_id);
			break;

		default:
			$query->where ('user_id',  $user->id);
	}

	return $query;
}

Obvoiusly this is a simplycistic case that you have to adapt to your situation, e.g. if the role is managed by gates and the scope is refrred to current logged in user, you can omit the $user parameter and do something like this:

$user = auth()->user();

if ($user->can('manager')
		$query->where ('team_id',  $user->team_id);
1 like
vincent15000's avatar

@Pippo Thank I have effectively read some discussions where the policies are used for another purpose than the authorizations.

So perhaps a question : is it a good idea to use the policies for another purpose than the authorizations ?

And is there a way to avoid passing the user role to the scope and identify the role only via the connected user ?

Sure it's possible to use auth()->user()->role, but a model (and its scopes) should not implement methods depending on a connected user.

Pippo's avatar

@vincent15000 Policies are tipically used to manage permissions for Models

In my projects i use the package Spatie / Laravel Permission that help managing roles and permissions for users and I often use it with Form Requests. Here you can find some useful information about Laravel Roles and Permissions: https://laravel-news.com/laravel-gates-policies-guards-explained

"Avoid passing the user role to the scope": yes, as i showed in previous post you could derive the role directly from the logged in user, perhaps via a relation if the information is on another table.

"A model (and its scopes) should not implement methods depending on a connected user": why not? And by the way it seemed that this was your initial request :-)

I think we are going a little off topic: I would recommend closing this topic and possibly opening other more specific ones

1 like
vincent15000's avatar

@Pippo I don't think that it's off topic. A model shoud not implement methods depending on a connected user because a model has to be independant and should exist out of any request environment. That's why I think that it would be better to check the role inside the controller (or in another place) but not in the model.

And this is directly related to my question : how can I customize queries according to the connected user's role. And in a better way with only one query.

Pippo's avatar

@vincent15000 Sorry, maybe I misunderstood the initial request, I understood that you were interested in how to manage a single scope for the different roles. In any case, I can suggest that you adopt the use of Service classes where you can relegate the Business Logic by unloading the controllers from this task.

Service classes are generally linked to a model or in any case to a specific activity. Therefore from any controller or other task you have to perform the same activity, you always call a method of a Service class without having to replicate the logic. For your need you could create methods that return an EloquentBuilder for the Model you are interested in, with the filters applied and that you can complete in the Controller, or vice versa pass an EloquentBuilder to the method of the Service and then receive it back with the filters applied

1 like

Please or to participate in this conversation.