Laravel Policies Explained: Authorization Step by Step

Arlind Musliu cofounder at Lucky Media
Arlind Musliu

February 10, 2025 · 4 min read

Laravel for Beginners: Using Policies for Authorization

2026 UPDATE - LARAVEL 13

We’re excited to announce that we have updated all of our blog post examples to reflect the new Laravel 13 version! Our previous examples were based on Laravel 10, but with the release of Laravel 13, we wanted to ensure that our readers have access to the most up-to-date information and examples.

What are Laravel Policies?

Policies in Laravel are classes that hold the authorization logic for a specific model. Think of them as the gatekeepers who decide if a user can do something with a resource. By using policies, you keep your controllers clean and focused on handling requests and responses.

Why Use Policies in Laravel?

Using policies in Laravel has several benefits:

  • Separation of Concerns: Policies help you keep your business logic separate from your authorization rules. This makes your code more organized, easier to test, and simpler to maintain.

  • Reusability: By placing your authorization rules in one place, can use them across multiple controllers and methods without repeating code.

  • Consistency: Policies ensure that your rules are applied the same way throughout your app, reducing the chance of security issues.

A Policy for our Blog example

Creating a Policy in Laravel

Creating a policy in Laravel is easy. You can generate a policy using the Artisan command:

php artisan make:policy PostPolicy

This command will create a new policy class in the app/Policies directory. If the directory doesn’t exist, Laravel will create it for you. The generated policy will be empty, but you can use the --model option to include predefined methods for common actions like viewing, creating, updating, and deleting:

php artisan make:policy PostPolicy --model=Post

This will create a policy class with methods for actions users might perform on the Post model. You can use this class to continue with our blog example.

Registering a Policy

In Laravel 13, if you follow the standard naming conventions, policies will be automatically discovered and registered by Laravel. We already have a Post model, so a corresponding PostPolicy class will be automatically linked.

However, if you prefer to manually register policies, you can do so in the boot method of your AppServiceProvider.

Modifying the Policy class

Here’s an example of a simple policy method that determines if a user can update a post:

namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id;
    }
}

In this example, the update method checks if the user’s ID matches the user_id on the post. If it does, the method returns true, allowing the user to update the post.

Using a Policy

Once your policies are created and registered, you can use them to control actions in your controllers or routes. For example, to check if a user can update a post, you can use the authorize method in your controller:

namespace App\Http\Controllers;

use App\Models\Post;
use App\Models\Tag;
use Illuminate\Http\Request;

class PostController extends Controller
{
    // Update the specified blog post
    public function update(Request $request, Post $post)
    {
		if ($request->user()->cannot('update', $post)) {
            abort(403);
        }

        $validatedData = $request->validate([
            'title' => 'required|max:255',
            'content' => 'required',
            // other validation rules...
        ]);

		$tags = $request->validate([
            'tags' => 'required',
        ]);

        $post->update($validatedData);

		// we modify the tags of the post by using the sync() method
        $post->tags()->sync($tags);

        return redirect()->route('posts.show', $post);
    }
}

This will check the update method in the PostPolicy class to determine if the user is allowed to update the post.

There are a couple of ways to do this. Let’s see them together:

  • Using a regular check through the request user.

// Update the specified blog post
    public function update(Request $request, Post $post)
    {
		if ($request->user()->cannot('update', $post)) {
            abort(403);
        }

        $validatedData = $request->validate([
            'title' => 'required|max:255',
            'content' => 'required',
            // other validation rules...
        ]);

		$tags = $request->validate([
            'tags' => 'required',
        ]);

        $post->update($validatedData);

		// we modify the tags of the post by using the sync() method
        $post->tags()->sync($tags);

        return redirect()->route('posts.show', $post);
    }
  • Using a Gate.

use Illuminate\Support\Facades\Gate;

	// Update the specified blog post
    public function update(Request $request, Post $post)
    {
    	Gate::authorize('update', $post);

        $validatedData = $request->validate([
            'title' => 'required|max:255',
            'content' => 'required',
            // other validation rules...
        ]);

		$tags = $request->validate([
            'tags' => 'required',
        ]);

        $post->update($validatedData);

		// we modify the tags of the post by using the sync() method
        $post->tags()->sync($tags);

        return redirect()->route('posts.show', $post);
    }
  • Using a middleware for our edit route to prevent access. However, a couple of lessons before we used a resource controller for posts, so we will need to slightly modify that. As you can see in the last line we can simply use can('edit', 'post'); to use our policy.

// We currently have this on our web.php file
Route::resource('posts', PostController::class);

// Let's remove the edit method from that
Route::resource('posts', PostController::class)->except('edit');
// we create a new route for the edit method
Route::get('/posts/{post}/edit', [PostController::class, 'edit'])
->name('post.edit')
->can('edit', 'post');

Conclusion

In Laravel 13, policies are essential for managing authorization. They offer a clean way to separate and centralize your authorization logic, keeping your code modular, reusable, and consistent. With automatic discovery and registration in Laravel 13, using policies is now easier than ever. By mastering policies, you can ensure your application remains secure and maintainable as it grows.

Upcoming Articles in the Series

  1. Laravel for Beginners: Roles and Permissions with Spatie package

  2. Laravel for Beginners: Differences of using Policies vs Roles and Permissions

  3. Laravel for Beginners: Using Laravel Spark with Stripe and Paddle

This article is part of our series Laravel for Beginners: A Step-by-Step Guide to Learn the Concepts.


Bring Your Ideas to Life 🚀

If you need help with a Laravel project let’s get in touch.

Lucky Media is proud to be recognized as a leading Laravel Development Agency

Technologies

Laravel
Arlind Musliu cofounder at Lucky Media
Arlind Musliu

Cofounder and CFO of Lucky Media

Stay up-to-date

Be updated with all news, products and tips we share!

Let’s chat

We partner with a limited number of brands each quarter to ensure senior-level attention on every project.

lokman and arlind headshots
Teamwork

Related posts

August 26, 2024

Laravel guide for Next.js developers
Laravel
Next.js

August 6, 2024

Hiring Expert Laravel Developers
Laravel
Business

August 5, 2024

Where to Find Laravel Developers?
Laravel
Business