An Introduction to Laravel Policy

Laravel 30 Dec 2018

If you heard about Laravel Policy and still not yet use that, this introduction to Laravel Policy post is for you then. In this tutorial, I will write a real-life tutorial that, how to use Laravel Policy for the beginner.

What is Laravel Policy

Laravel policy is a part of Authorization of Laravel that help you to protect content or resources from unauthorized access.

Just imagine a simple concept that you have a blog that contains users and posts. Normally the post can be visible to every visitor, however, to edit a post, you need to be the owner of the post. In this tutorial, I will show you how to show the edit post option to the post owner only.

The basic concept of this apps is-

  1. A user can create a post
  2. A post can be viewed by visitor / user
  3. The post creator only can edit the post
  4. The post creator only can able to delete

Basic Configuration

First, let's connect with Database. In your .env file, update like follow. My database name is laravel-policy.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel-policy
DB_USERNAME=root
DB_PASSWORD=

Next, need to create the migration, model and controller for posts and users table.

php artisan make:model User -m -c
php artisan make:model Post -m -c

Let's define migration now.

User

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('username');
    $table->string('email')->unique();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

Post

Schema::create('posts', function (Blueprint $table) {
  $table->increments('id');
  $table->string('title');
  $table->text('deatils');
  $table->integer('user_id');
  $table->integer('flag');
  $table->timestamps();
});

Once, you have done this part, now run the migration.

php artisan migrate

If everything goes smoothly, you will see two tables in your database called users and posts. Now you may record data in your tables. You may go for seeding data or add manually. To keep this tutorial show, I just skip this step.

Create Policy

The ideal way to define a policy is to follow the model name. In our case, our model name is Post, so that our policy name should be PostPolicy to the authorized user to edit or delete. The artisan command to do that is-

php artisan make:policy PostPolicy

This command make:policy will generate an empty policy class in the App\Policies folder. In addition, you can suffix --model=Post to create CRUD.

Writing Policy

Now, let write the policy for the post where the post id is 1 that belongs to a user who's id is 1. So, the post is available to view from any user or visitor, however, in order to update or delete, you need to be a user who's id is 1.

Now, defining the update method to restrict the update option from mass people.

<?php

namespace App\Policies;

use App\User;
use App\Post;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
    use HandlesAuthorization;

    /**
     * Determine if the given post can be updated by the user.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return bool
     */
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

This update method will check whether the post creator is this user or not. It will return true once it matches otherwise, returns false.

Registering a Policy.

Once you have defined policy, you need to register the policy in the app/Providers/AuthServiceProvider.

<?php

namespace App\Providers;

use App\Post;
use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
        Post::class => PostPolicy::class
    ];
}

How to use

Once you are in this stage that means, you have done everything successfully. Now, you need to use that.

Via View

In the view, you can use @can and @cannot directive.

@can('update', $post)
    <!-- The Current User Can Update The Post -->
@endcan
@cannot('update', $post)
    <!-- The Current User Can't Update The Post -->
@endcannot

Via Model

In the model, you can use in the following way-

if ($user->can('update', $post)) {
    //
}

Via Controller

Even you can use via controller also. Cool, right?

public function update(Request $request, Post $post)
{
	$this->authorize('update', $post);

	// The current user can update the blog post...
}

Sweet. Hope, you will like this. If you love this, feel free to share.

You can get this code in the following repository. https://github.com/laravel-school/introduction-laravel-policy

Thank you.