Laravel,有一个带有自定义策略方法的自定义控制器方法吗?

问题描述 投票:0回答:2

我有一个资源控制器,想要为 destroyMany 添加额外的自定义策略方法 在删除用户之前,我会检查用户是否是管理员。

默认方法工作正常

控制器方法 政策方法
索引 查看任意
展示 查看
创建 创建
商店 创建
编辑 更新
更新 更新
摧毁 删除
摧毁许多 摧毁许多

控制器 destroyMany 方法被调用,策略未被调用 或者我应该坚持使用盖茨的这种额外方法? 文档说我可以为方法和策略指定任何名称,两者如何链接?

destroyMany->destroyMany 或 destroyMany->deleteMany 将是一个很好的设置。

这将是我的资源控制器(它应该驻留在哪里)的一个很好的补充

class ResourceController extends Controller
{
    public function __construct()
    {
      $this->middleware('auth:api');
      $this->authorizeResource(Resource::class, 'resource');
    }

    public function index()
    {

        return ResourceCollection::collection(Resource::all());
    }

    public function destroyMany(Request $request)
    {
        // gets called but needs a policy which isn't called
    }
}

政策

class ResourcePolicy
{
    use HandlesAuthorization;

    /**
     * Create a new policy instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    public function viewAny(User $user)
    {
        // works
        return $user->hasAnyRoles(['admin', 'superAdmin']);
    }

    public function delete(User $user, Resource $resource)
    {
       // works
        return $user->hasAnyRoles(['admin', 'superAdmin']);
    }

    public function deleteMany(User $user, Resource $resource)
    {
        // not called because the controller method needs to be hooked up, like the other methods
       
    }
}
laravel controller resources policies
2个回答
9
投票

要使添加策略方法起作用,您需要更新控制器的

resourceAbilityMap
。将以下内容添加到您的控制器应该可以解决问题:

protected function resourceAbilityMap()
{
    return array_merge(parent::resourceAbilityMap(), [
        'destroyMany' => 'deleteMany'
    ]);
} 

此外,如果您未从

deleteMany
策略方法返回任何内容,则会导致 403。

如果您的路由/控制器方法没有接收模型的实例,那么您还需要更新从

resourceMethodsWithoutModels
方法返回的数组:

protected function resourceMethodsWithoutModels()
{
    return array_merge(parent::resourceMethodsWithoutModels(), ['destroyMany']);
}

0
投票

另一种方法是扩展策略能力并明确地调用它:有点乏味(您必须在控制器的方法中手动调用

authorize
),但给定的能力也可以在其他地方访问(例如刀片模板、服务,无论在哪里)你可以使用
can
助手...)。

AuthServiceProvider

use Illuminate\Support\Facades\Gate;

public function boot(): void
{
  Gate::define('destroyMany', [ResourcePolicy::class, 'deleteMany']);
}

ResourceController

public function destroyMany(Request $request)
{
  $this->authorize('destroyMany');
  // ...
}

任何地方

$user->can('destroyMany');

来源:Laravel 文档

© www.soinside.com 2019 - 2024. All rights reserved.