我有一个资源控制器,想要为 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
}
}
要使添加策略方法起作用,您需要更新控制器的
resourceAbilityMap
。将以下内容添加到您的控制器应该可以解决问题:
protected function resourceAbilityMap()
{
return array_merge(parent::resourceAbilityMap(), [
'destroyMany' => 'deleteMany'
]);
}
此外,如果您未从
deleteMany
策略方法返回任何内容,则会导致 403。
如果您的路由/控制器方法没有接收模型的实例,那么您还需要更新从
resourceMethodsWithoutModels
方法返回的数组:
protected function resourceMethodsWithoutModels()
{
return array_merge(parent::resourceMethodsWithoutModels(), ['destroyMany']);
}
另一种方法是扩展策略能力并明确地调用它:有点乏味(您必须在控制器的方法中手动调用
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 文档。