Get started with 33% off your first certification using code: 33OFFNEW

A guide to Policies in Laravel

3 min read
Published on 4th June 2024

Laravel is a powerful PHP framework that provides developers with various tools to manage the complexities of web application development. One of these tools is Policies, a feature that helps in organizing authorization logic for different parts of your application. This guide will walk you through what Policies are, how to create and implement them, and best practices for using Policies in Laravel.

What are Policies in Laravel?

Policies in Laravel are classes that organize authorization logic around a particular model or resource. They serve as a way to encapsulate permissions for CRUD (Create, Read, Update, Delete) operations and other actions, ensuring that your authorization logic is clean, consistent, and easy to manage.

Creating a Policy

To create a policy in Laravel, you can use the Artisan command. For example, let's say you have a Post model and you want to create a policy for it.

  1. Generate the Policy:

    php artisan make:policy PostPolicy --model=Post
    

    This command creates a new PostPolicy class in the app/Policies directory and associates it with the Post model.

  2. Define the Policy Methods: Open the generated PostPolicy class and define methods for the actions you want to authorize. Each method should correspond to an action your users can perform on the Post model.

    namespace App\Policies;
    
    use App\Models\Post;
    use App\Models\User;
    use Illuminate\Auth\Access\HandlesAuthorization;
    
    class PostPolicy
    {
        use HandlesAuthorization;
    
        /**
         * Determine if the given post can be viewed by the user.
         *
         * @param  \App\Models\User  $user
         * @param  \App\Models\Post  $post
         * @return bool
         */
        public function view(User $user, Post $post)
        {
            return $user->id === $post->user_id;
        }
    
        /**
         * Determine if the given post can be created by the user.
         *
         * @param  \App\Models\User  $user
         * @return bool
         */
        public function create(User $user)
        {
            return true;
        }
    
        /**
         * Determine if the given post can be updated by the user.
         *
         * @param  \App\Models\User  $user
         * @param  \App\Models\Post  $post
         * @return bool
         */
        public function update(User $user, Post $post)
        {
            return $user->id === $post->user_id;
        }
    
        /**
         * Determine if the given post can be deleted by the user.
         *
         * @param  \App\Models\User  $user
         * @param  \App\Models\Post  $post
         * @return bool
         */
        public function delete(User $user, Post $post)
        {
            return $user->id === $post->user_id;
        }
    }
    

Registering the Policy

After defining your policy methods, you need to register the policy. Open the AuthServiceProvider class and add the policy to the policies array.

  1. Register the Policy:
    namespace App\Providers;
    
    use App\Models\Post;
    use App\Policies\PostPolicy;
    use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
    
    class AuthServiceProvider extends ServiceProvider
    {
        /**
         * The policy mappings for the application.
         *
         * @var array
         */
        protected $policies = [
            Post::class => PostPolicy::class,
        ];
    
        /**
         * Register any authentication / authorization services.
         *
         * @return void
         */
        public function boot()
        {
            $this->registerPolicies();
        }
    }
    

Using Policies in Controllers

With your policy defined and registered, you can use it in your controllers to authorize actions. Laravel provides several methods to work with policies, such as authorize, can, and cannot.

  1. Authorize Actions:
    namespace App\Http\Controllers;
    
    use App\Models\Post;
    use Illuminate\Http\Request;
    
    class PostController extends Controller
    {
        public function show(Post $post)
        {
            $this->authorize('view', $post);
            return view('posts.show', compact('post'));
        }
    
        public function update(Request $request, Post $post)
        {
            $this->authorize('update', $post);
            // Update the post
        }
    
        public function destroy(Post $post)
        {
            $this->authorize('delete', $post);
            // Delete the post
        }
    }
    

Best Practices for Using Policies

  1. Keep Policies Focused: Each policy should focus on a single model or resource, making it easier to manage and understand.
  2. Use Gate for Complex Logic: For complex authorization logic that spans multiple models, use Gates instead of Policies.
  3. DRY Principle: Don’t repeat yourself. Reuse policy methods where possible to avoid duplication.
  4. Granular Permissions: Define granular permissions to ensure fine-grained control over what users can and cannot do.

Policies in Laravel provide a structured way to handle authorization logic, ensuring your application remains secure and maintainable. By creating, registering, and using policies effectively, you can manage user permissions cleanly and consistently across your application. This guide covers the basics, but there's a lot more to explore, including middleware integration and policy events, to fully leverage Laravel's powerful authorization system.