laravel-permission icon indicating copy to clipboard operation
laravel-permission copied to clipboard

Need to conditionally load user permissions (abilities) via eloquent as flattened array

Open sts-ryan-holton opened this issue 11 months ago • 8 comments

Description

Hi, I need to be able to load "abilities" for a user within my system as a flattened array. Note that a User isn't always the logged in user and is sometimes a tenant of the system. Right now I'm doing this with an appended attribute, but this is loaded everywhere and is calling the Lazy load error.

How can I reproduce the following function but via eloquent when doing User::all() in the system:

/**
 * Get permissions for user
 */
public function getAbilitiesAttribute(): array
{
    try {
        return $this->getAllPermissions()->pluck('name')->flatten()->toArray();
    } catch (\Exception $err) {

    }

    return [];
}

Steps To Reproduce

n/a

Example Application

n/a

Version of spatie/laravel-permission package:

6.10.1

Version of laravel/framework package:

11.38.2

PHP version:

8.3.8

Database engine and version:

MySQL 8

OS: Windows/Mac/Linux version:

ac

sts-ryan-holton avatar Jan 21 '25 10:01 sts-ryan-holton

Not an issue, must be a discussion

parallels999 avatar Jan 21 '25 13:01 parallels999

@parallels999 Okay, but still my discussion is still a valid point, how might we achieve this functionality with the package to reduce and optimise the number of queries. Maybe this could be a new feature?

sts-ryan-holton avatar Jan 29 '25 19:01 sts-ryan-holton

@sts-ryan-holton You mentioned that part of the concern you raised is related to lazy-loading. Does the lazy-loading issue resolve when using v6.13.0 (Ref: #2776 ) ?

drbyte avatar Feb 05 '25 15:02 drbyte

Just eager load relations

User::with(['roles', 'roles.permissions', 'permissions'])->all();

Now abilities should be available without lazy load errors

parallels999 avatar Feb 05 '25 15:02 parallels999

This appears to work without errors:

    public function getAbilitiesAttribute(): array
    {
        try {
            return $this
                ->loadMissing(['roles', 'roles.permissions', 'permissions'])
                ->getAllPermissions()->pluck('name')->flatten()->toArray();
        } catch (\Exception $err) {

        }

        return [];
    }

drbyte avatar Feb 16 '25 19:02 drbyte

I don't want to load it everywhere via my User model though. What I'm saying is that's an inefficient way of doing it but works for now since the package doesn't seem to provide a flattened approach to doing it, say, within a controller directly. How do I achieve this?

sts-ryan-holton avatar Feb 18 '25 15:02 sts-ryan-holton

I don't want to load it everywhere via my User model though.

Do you mean that you'd just prefer that this package build it into the trait, so that it becomes part of the User model?

that's an inefficient way of doing it but works for now since the package doesn't seem to provide a flattened approach to doing it, say, within a controller directly.

Can you give an example of how you'd use this in a controller?

Third, what would be the "ideal" interface that you have in mind?

drbyte avatar Mar 01 '25 23:03 drbyte

Dear contributor,

because this issue seems to be inactive for quite some time now, I've automatically closed it. If you feel this issue deserves some attention from my human colleagues feel free to reopen it.

spatie-bot avatar Jun 30 '25 10:06 spatie-bot