首页 > 解决方案 > 使资源详细信息页面的操作可选

问题描述

假设我对Product资源有行动“禁令”,而Product模型有is_banned领域。Product已被禁止(is_banned=1)的详情页无需显示“禁止”动作。

Laravel Nova 文档提供了基于管理员是否被授权执行隐藏操作的示例:

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

canSee但它没有涵盖当在单个资源的上下文中调用此方法时(在其详细信息页面上),我如何在我提供解析的闭包中获取当前资源的模型实例。

actions()方法是我们注册可用操作的地方,在我的例子中属于ProductNova 资源类,但它也无法访问 Eloquent 模型的上下文。

如何做到这一点?

标签: laravellaravel-nova

解决方案


在做了一些调试后,我发现资源的actions()方法接收Laravel\Nova\Http\Requests\NovaRequest具有findModelOrFail()方法的实例,并且对于单个资源(例如,查看资源的详细信息页面时)请求也获取resourceId参数。

因此,根据resourceId请求中的存在,我现在可以确定我是否处于单一资源操作的上下文中。然后我会用这个 id 获取资源的模型并检查它的is_banned属性来解析资源的可用操作。

我的行动解决逻辑最终是:

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

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

    return [new Actions\BanProduct];
}

请注意,findModelOrFail()方法可以不带$resourceId参数调用,并且在这种情况下会自动resourceId从请求中获取值,但是直接指定时代码的意图会更清晰。


推荐阅读