Laravel

Lesson 08

Policies and authorization

Use policies or gates for model-level authorization so access rules are named, reusable, and testable.

Good Code

app/Http/Controllers/ReviewController.php
<?php

namespace App\Http\Controllers;

use App\Models\Review;
use Illuminate\Support\Facades\Gate;

final class ReviewController
{
    public function update(UpdateReviewRequest $request, Review $review)
    {
        // A named policy decides whether this user may update the review.
        Gate::authorize('update', $review);

        $review->update($request->validated());

        return $review->fresh();
    }
}

Bad Code

app/Http/Controllers/ReviewController.php
<?php

public function update(Request $request, Review $review)
{
    // Inline ownership checks drift when other actions need the same rule.
    if ($request->user()->id !== $review->user_id && ! $request->user()->is_admin) {
        abort(403);
    }

    $review->update($request->all());

    return $review;
}

Review Notes

What to review

Good Code

The good version makes authorization visible as a named policy decision before mutation. That rule can be reused by controllers, jobs, or tests.

Bad Code

The bad version repeats an ownership check inline and mixes authorization with unchecked input writes.

Takeaways

  • Authorization should read as a named rule at the controller boundary instead of scattered ownership checks.