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

farkhod's avatar

How can I use api resource with gates?

Hello

I have a users, and I return them like this

public function index(Request $request)
{
    return [
        'users' => User::get()
            ->latest()
            ->paginate(10)
            ->withQueryString()
            ->through(function ($user) {
                return [
                    'id' => $user->id,
                    'name' => $user->name,
                    // other user fields...
                    'can' => [
                        'edit' => auth()->user()->can('user-edit', $user),
                        'delete' => auth()->user()->can('user-delete', $user),
                    ]
                ];
            }),
    ];
}

How can I use api resource with gates?

Is possible like this?

public function index(Request $request)
{
    return [
        'users' => UserResource::collection(
            User::get()
                ->latest()
                ->paginate(10)
                ->withQueryString()
        )->can(function ($user) {
            return [
                'edit' => auth()->user()->can('user-edit', $user),
                'delete' => auth()->user()->can('user-delete', $user),
            ];
        })
    ];
}

0 likes
13 replies
farkhod's avatar

I want to clarify, I use Inertiajs and all works fine

martinbean's avatar

@farkhod Resource classes have nothing to do with authorisation. A resource class just formats the models you give it. So you should have already authorised the request using a policy or gate before querying the database. The only models being passed to a resource should be models you’ve authorised the user can see.

farkhod's avatar

I know about it. The problem is that I need to return user data and at the same time check whether actions are available for an user. For example, actions may depend on status.

mkshingrakhiya's avatar

Take a look at this...

public function index(Request $request)
{
    return [
        'users' => User::get()
            ->latest()
            ->paginate(10)
            ->withQueryString()
            ->map(function ($user) {
                return [
                    'id' => $user->id,
                    'name' => $user->name,
                    'can' => [
                        'edit' => auth()->user()->can('user-edit', $user),
                        'delete' => auth()->user()->can('user-delete', $user),
                    ]
                ];
            }),
    ];
}
farkhod's avatar

I do exactly the same, I gave the example above.

But I want to use the api resource

mkshingrakhiya's avatar

Define accessor in the User model.

public function getCanAttribute(): array
{
	return [
		'edit' => auth()->user()->can('user-edit', $this),
		'delete' => auth()->user()->can('user-delete', $this)
	];
}

And then return the attribute from the resource class.

public function toArray($request)
{
    return [
		// other attributes/columns...
        'can' => $this->can,

		// or (below isn't tested but should work fine)
		'can' => $this->when($this->hasAppended('can'), $this->can)
    ];
}
mkshingrakhiya's avatar

Didn't get what you're asking but if you add items in the accessor array or remove from it, it will also be added or removed from the response.

farkhod's avatar

This will work. But it seems to me that this is not a very elegant solution.

mkshingrakhiya's avatar

Sorry to disappoint you but I don't find anything more cleaner than this either. Let me know if you find more elegant solution. Have a good day!

Snapey's avatar

you are checking if the authenticated user can edit other users, however, APIs typically are not authenticated ?

1 like
farkhod's avatar

In my case, APIs always for authenticated users

Please or to participate in this conversation.