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

grayorc's avatar

Duplicated queries

Hey guys 👋 I'm working on a couple of policy methods in Laravel, and I noticed that duplicate queries are being made. Here's an example of what I'm currently doing in UserPolicy.php:

public function edit(User $user, User $model): bool
{
    if ($user->hasPermission('edit-user')) {
        if ($model->permissions()->exists()) {
            return false;
        }
        return true;
    }
    return false;
}

public function delete(User $user, User $model): bool
{
    if ($user->hasPermission('remove-user')) {
        if ($model->permissions()->exists()) {
            return false;
        }
        return true;
    }
    return false;
}
0 likes
8 replies
tykus's avatar

I don't understand the logic... if the authenticated user has permission to edit-user or remove-user; then why do you need to also check if the subject User has any permissions of their own?

grayorc's avatar

@tykus Because users with permissions are admins or mods, and I don't want them to be able to mess with other admins. I will add edit-admin and delete-admin in the future.

tykus's avatar

@grayorc you know what would much better communicate that intent... a well named method!

return $user->hasPermission('edit-user') && ! $model->isAdmin();

Much more readable!

Anyway, what are these duplicate queries?

1 like
grayorc's avatar

@tykus thanks for the suggestion

duplicated queries

select exists(select * from `permissions` inner join `permission_user` on `permissions`.`id` = `permission_user`.`permission_id` where `permission_user`.`user_id` = 1) as `exists`
select exists(select * from `permissions` inner join `permission_user` on `permissions`.`id` = `permission_user`.`permission_id` where `permission_user`.`user_id` = 1) as `exists`

Although I'm using automaticallyEagerLoadRelationships(), these where repeated for each user

tykus's avatar
tykus
Best Answer
Level 104

@grayorc this is Eloquent Builder logic; there is no issue of eager-loading or not.

$model->permissions()->exists()

You can load a relationship count or an exists aggregate function on the Users query using the withCount or withExists methods:

User::query()
  ->withExists('permissions')
  ->get()

Then the logic in the Policy would look like this:

return $user->hasPermission('edit-user') && ! $model->permissions_exists;

But this might not work for all cases whenever you forget to load that exists property on a User instance (giving false negatives); an isAdmin implementation could handle possible permissions, permissions_exists or permissions_count properties, or fallback to the Eloquent Builder query when needed.

1 like
grayorc's avatar

@tykus I tried the withCount and withExists methods, but they still resulted in duplicated queries. I think implementing isAdmin is probably the best approach, and that's the direction I'm going to take. Thanks for your help.

and also I really appreciate all your suggestions! @ghabe @rodrigo.pedra

1 like
rodrigo.pedra's avatar

Are you testing with the same user?

I mean, the $user and $model are the same record, like one user trying to edit themselves?

If so, that is the reason.

Please or to participate in this conversation.