Laravel多作者权限校验代码冗余问题及优化方案咨询
Hey there! I totally get it—repeating that author ID ownership check in every controller action feels messy and violates the DRY (Don't Repeat Yourself) principle. Let's fix this with a few clean, Laravel-native approaches depending on your needs.
Option 1: Enhance Your author Middleware to Handle Ownership
The quickest win is to move that controller validation logic directly into your middleware. This way, every route in your auth + author group will automatically validate that the author ID belongs to the authenticated user—no redundant controller code needed.
Here's the updated middleware code:
public function handle($request, Closure $next) { // First, confirm user is logged in if (!auth()->check()) { return redirect('/dashboard')->with("error", "Please log in first"); } $user = auth()->user(); // Keep your original check for existing author profiles if ($user->authorsProfile->isEmpty()) { return redirect('/dashboard')->with("error", "Only Authors Allowed"); } // Add ownership validation for the requested author ID if (isset($request->id)) { $author = Author::find($request->id); if (!$author || $author->user_id !== $user->id) { return back()->with("error", "This Author is not you"); } } return $next($request); }
With this change, you can completely remove the ownership check from your controller:
public function dashboard($id) { // No validation needed here—middleware already handled it return view('frontend.author.dashboard'); }
Option 2: Use Route Model Binding with User Scoping
For an even more elegant solution, leverage Laravel's route model binding. This lets Laravel automatically fetch the Author model for you, and we can add a scope to ensure it only returns authors belonging to the current user.
First, update your route to use model binding (replace {id} with {author}):
Route::group(['middleware' => ['auth','author']], function() { Route::get('authorsarea/{author}','AuthorController@dashboard')->name('author-dashboard'); });
Next, add a global scope to your Author model to restrict queries to the authenticated user:
// In your Author model protected static function booted() { static::addGlobalScope('user', function ($query) { if (auth()->check()) { $query->where('user_id', auth()->id()); } }); }
Alternatively, if you don't want a global scope, define a custom route binding in your RouteServiceProvider:
// In RouteServiceProvider@boot Route::bind('author', function ($value) { return Author::where('id', $value) ->where('user_id', auth()->id()) ->firstOrFail(); });
Now your controller can directly accept the Author model—Laravel will automatically throw a 404 if the author doesn't exist or doesn't belong to the user:
public function dashboard(Author $author) { // $author is guaranteed to belong to the current user return view('frontend.author.dashboard', compact('author')); }
Option 3: Extract Validation to a Reusable Trait
If you only need this validation in specific controller actions (not the entire middleware group), create a trait to reuse the logic:
// app/Http/Controllers/Traits/ValidatesAuthorOwnership.php namespace App\Http\Controllers\Traits; use App\Models\Author; use Illuminate\Support\Facades\Auth; use Illuminate\Http\RedirectResponse; trait ValidatesAuthorOwnership { protected function validateAuthorOwnership($authorId): Author|RedirectResponse { $author = Author::find($authorId); if (!$author || $author->user_id !== Auth::id()) { return back()->with("error", "This Author is not you"); } return $author; } }
Then use it in your controller:
use App\Http\Controllers\Traits\ValidatesAuthorOwnership; class AuthorController extends Controller { use ValidatesAuthorOwnership; public function dashboard($id) { $author = $this->validateAuthorOwnership($id); if ($author instanceof RedirectResponse) { return $author; } return view('frontend.author.dashboard', compact('author')); } }
Which Option Should You Pick?
- Middleware: Ideal if every route in your
authorgroup needs ownership validation. Keeps controllers clean and centralized. - Route Model Binding: The most Laravel-idiomatic approach, especially if you need to work with the
Authormodel in your controller. - Trait: Perfect for one-off controller actions where you don't want to apply validation across an entire route group.
内容的提问来源于stack exchange,提问作者Pedro

