You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何精简PostController中仅允许文章作者访问编辑页的权限判断代码?

优雅精简Laravel模型权限校验的几种方案

嘿,这个场景我太熟了!重复写这种“判断当前用户是否是资源所有者”的逻辑确实很冗余,Laravel给我们提供了几种非常优雅的解决方式,给你梳理一下最常用的几个:


1. 使用Laravel授权策略(Policy)—— 官方推荐的最佳实践

这是处理模型级权限控制的标准方式,不仅能精简控制器代码,还能在视图、命令行等其他地方复用权限逻辑。

步骤:

  • 首先生成对应模型的策略文件:
php artisan make:policy VocabularyPolicy
  • 在生成的app/Policies/VocabularyPolicy.php里添加update方法(对应编辑/更新权限):
public function update(User $user, Vocabulary $vocabulary)
{
    // 校验当前用户是否是词汇的所有者
    return $user->id === $vocabulary->user_id;
}
  • 在app/Providers/AuthServiceProvider.php中注册策略:
protected $policies = [
    Vocabulary::class => VocabularyPolicy::class,
];
  • 然后在控制器里就可以用一行代码完成校验:
public function edit(Vocabulary $vocabulary)
{
    // 如果校验不通过,Laravel会自动抛出403异常,你也可以自定义响应
    $this->authorize('update', $vocabulary);
    
    // 正常返回视图逻辑
    return view('vocabularies.edit', compact('vocabulary'));
}
  • 更省心的方式:直接在路由层面绑定权限校验,不用碰控制器:
Route::get('/vocabularies/{vocabulary}/edit', [PostController::class, 'edit'])
    ->middleware('can:update,vocabulary');

2. 自定义中间件 —— 适合跨控制器的通用权限

如果多个控制器都需要类似的“资源所有者校验”,自定义中间件是个不错的选择。

步骤:

  • 生成中间件:
php artisan make:middleware EnsureVocabularyBelongsToUser
  • 在app/Http/Middleware/EnsureVocabularyBelongsToUser.php里编写校验逻辑:
public function handle(Request $request, Closure $next)
{
    // 从路由参数中获取词汇模型
    $vocabulary = $request->route('vocabulary');
    
    if ($vocabulary->user_id !== Auth::id()) {
        return redirect()->route('home')->with('danger', 'You cannot edit another user\'s vocabulary.');
    }

    return $next($request);
}
  • 在app/Http/Kernel.php的$routeMiddleware数组中注册中间件:
protected $routeMiddleware = [
    // ...其他中间件
    'vocab.owner' => \App\Http\Middleware\EnsureVocabularyBelongsToUser::class,
];
  • 使用方式:
    • 给单个路由添加:
    Route::get('/vocabularies/{vocabulary}/edit', [PostController::class, 'edit'])->middleware('vocab.owner');
    
    • 给控制器指定方法批量添加(在控制器构造函数里):
    public function __construct()
    {
        $this->middleware('vocab.owner')->only(['edit', 'update']);
    }
    

3. 控制器私有共享方法 —— 快速精简当前控制器代码

如果只是当前PostController里的几个方法需要这个校验,不想搞复杂的策略或中间件,直接写个私有方法复用就行。

实现:

在PostController里添加一个私有方法:

private function ensureOwnsVocabulary(Vocabulary $vocabulary)
{
    if ($vocabulary->user_id !== Auth::id()) {
        return redirect()->route('home')->with('danger', 'You cannot edit another user\'s vocabulary.');
    }
}

然后在需要的方法里调用:

public function edit(Vocabulary $vocabulary)
{
    $this->ensureOwnsVocabulary($vocabulary);
    // 返回视图...
}

public function update(Vocabulary $vocabulary)
{
    $this->ensureOwnsVocabulary($vocabulary);
    // 更新逻辑...
}

最后小建议

如果项目比较规范,优先用授权策略,它的扩展性最强,后续要加其他权限(比如删除、查看)也非常方便;如果是多个控制器共用的通用权限,选中间件;只是当前控制器用的话,私有方法最快捷。

内容的提问来源于stack exchange,提问作者entithat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:20:48