Simplifying authorization logic with Policies in Laravel
Laravel devs, here's a gem for you: π Simplify your authorization logic with Policies. Manage permissions and access control in a clean, organized way! In this blog post, we'll explore how to use Laravel Policies to handle authorization logic and provide a real-life example to demonstrate their benefits.
Why Use Policies?
- Separation of Concerns: Keeps authorization logic separate from your controllers and models.
- Reusability: Define your authorization logic once and reuse it across your application.
- Maintainability: Centralizes your authorization logic, making it easier to manage and update.
Step-by-Step Implementation
Let's walk through the process of setting up and using policies in a Laravel application.
Step 1: Creating the Policy
First, you need to create a policy for the model you want to authorize. In this example, we'll create a policy for the Post
model.
php artisan make:policy PostPolicy
This command will create a policy file in the app/Policies
directory.
Step 2: Defining the Policy Methods
Open the generated policy file and define the authorization methods. Each method corresponds to a specific action a user can perform on the model.
// app/Policies/PostPolicy.php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any posts.
*/
public function viewAny(User $user)
{
return $user->is_admin;
}
/**
* Determine whether the user can view the post.
*/
public function view(User $user, Post $post)
{
return $user->id === $post->user_id || $user->is_admin;
}
/**
* Determine whether the user can create posts.
*/
public function create(User $user)
{
return $user->is_admin || $user->is_writer;
}
/**
* Determine whether the user can update the post.
*/
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
/**
* Determine whether the user can delete the post.
*/
public function delete(User $user, Post $post)
{
return $user->id === $post->user_id && $user->is_admin;
}
}
Step 3: Registering the Policy
Next, you need to register the policy in the AuthServiceProvider
.
// app/Providers/AuthServiceProvider.php
namespace App\Providers;
use App\Models\Post;
use App\Policies\PostPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Post::class => PostPolicy::class,
];
public function boot()
{
$this->registerPolicies();
}
}
Step 4: Using Policies in Controllers
Finally, you can use the policy methods in your controllers to authorize actions.
// app/Http/Controllers/PostController.php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class PostController extends Controller
{
public function index()
{
$this->authorize('viewAny', Post::class);
$posts = Post::all();
return view('posts.index', ['posts' => $posts]);
}
public function show(Post $post)
{
$this->authorize('view', $post);
return view('posts.show', ['post' => $post]);
}
public function create()
{
$this->authorize('create', Post::class);
return view('posts.create');
}
public function store(Request $request)
{
$this->authorize('create', Post::class);
$post = Post::create($request->all());
return redirect()->route('posts.show', $post);
}
public function edit(Post $post)
{
$this->authorize('update', $post);
return view('posts.edit', ['post' => $post]);
}
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
$post->update($request->all());
return redirect()->route('posts.show', $post);
}
public function destroy(Post $post)
{
$this->authorize('delete', $post);
$post->delete();
return redirect()->route('posts.index');
}
}
Example: Managing Post Permissions
In a real-life scenario, you might have different types of users (e.g., admins, writers, readers) with varying permissions for managing posts. Using policies, you can define these permissions in a centralized location and enforce them consistently across your application.
Creating Dummy Data
Let's generate some dummy data to work with.
php artisan tinker
// Inside Tinker
User::factory()->create(['name' => 'Admin', 'is_admin' => true]);
User::factory()->create(['name' => 'Writer', 'is_writer' => true]);
Post::factory()->count(5)->create(['user_id' => 1]); // Posts by Admin
Post::factory()->count(5)->create(['user_id' => 2]); // Posts by Writer
This command will generate dummy users and posts with different roles.
Viewing the Posts
Access the /posts
route in your browser to see the list of posts.
Conclusion
Using policies in Laravel allows you to manage permissions and access control in a clean, organized way. By following the steps outlined in this blog post, you can leverage the power of policies to enforce authorization logic consistently across your Laravel applications.
Found this helpful?
If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!