0
votes

Let's say I have action "Ban" for Product resource and Product model has is_banned field. There is no need to show "Ban" action on details page of Product that is already banned (is_banned=1).

Laravel Nova documentation provides example of hiding actions based on whether or not admin is authorized to perform it:

public function actions(Request $request)
{
    return [
        (new Actions\EmailAccountProfile)->canSee(function ($request) {
            return $request->user()->can(
                'emailAnyAccountProfile', User::class
            );
        }),
    ];
}

But it doesn't cover how can I get current resource's model instance in the closure I provide for canSee resolution when this method is called in the context of a single resource (on it's details page).

actions() method is where we register available actions and in my case belongs to Product Nova resource class, but it doesn't have access to Eloquent model's context neither.

How can this be achieved?

1

1 Answers

1
votes

After doing some debugging I found out that resource's actions() method receives Laravel\Nova\Http\Requests\NovaRequest instance that has findModelOrFail() method and for a single resource (for example, when viewing resource's details page) request also gets resourceId parameter.

So based on resourceId presence in the request I could now determine whether or not I am in the context of single resource operation. Then I would fetch resource's model with this id and check it's is_banned attribute to resolve available actions for resource.

My actions resolution logic ended up being:

public function actions(Request $request)
{
    if ($request->resourceId !== null) {
        $product = $request->findModelOrFail($request->resourceId);

        if ($product->is_banned) {
            return [];
        }
    }

    return [new Actions\BanProduct];
}

Note that findModelOrFail() method can be called without $resourceId argument and will automatically get resourceId value from the request in such scenario, but code's intent is clearer when specifying it directly.