Chris Arter
Chris Arter

Follow

Chris Arter

Follow
Demystifying Gates in Laravel

Photo by Danny Lines on Unsplash

Demystifying Gates in Laravel

If you find the concept of "gates" in Laravel a bit confusing, don't worry. You're not alone.

Chris Arter's photo
Chris Arter
Ā·Jan 5, 2023Ā·

2 min read

I found gates a bit confusing for quite some time. I just ignored them for the first couple of years developing Laravel applications. I was confused by the naming and wasn't sure exactly what they were.

Let me get this out of the way:

Gates are permissions.

That should clarify a lot of the confusion. They're simply portable logic you can check for across your app. For example, you can define a gate in a service provider. This example is from the docs:

    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });

Now, we can check for this in several different places in our app. For example, our controller (another example from the docs):

class PostController extends Controller
{
    public function update(Request $request, Post $post)
    {
        if (! Gate::allows('update-post', $post)) {
            abort(403);
        }

        // Update the post...
    }
}

You can also reference it in things like a blade file:

@can('update-post')
<a href="{{ route('posts.edit', ['post' => $post]) }}">Update</a>
@endcan

Use Policies Instead

Now that you get an idea of what gates are, my strong suggestion is to use policies instead.

Policies are classes with related methods around a particular model or idea. When creating a policy for a model, you can pass the --model=Post flag which will create a policy with authorization logic around each CRUD (create, read, update, delete) operation on your model.

Here's an example of a model policy class:

class PostPolicy {

  public function view(User $user, Post $post)
  {
     // ...
  }

  public function create(User $user)
  {
     // ...
  }

  public function update(User $user, Post $post)
  {
     // ...
  }

  public function delete(User $user, Post $post)
  {
     // ...
  }
}

You don't need to manually write various gates in your service provider. You can simply create a model policy, and Laravel provides an easy API throughout the app to use this policy.

This is an example from the docs of what a check looks like in a policy:

class PostPolicy
{
    // ...

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

Now we can easily check against this logic in places like our routes file:

Route::get('/posts/{post}/edit', [PostsController::class, 'update'])->middleware('can:update,post');

The cool part about the snippet above is ->middleware('can:update,post'); method.

In a single line of code, it creates a middleware that will automatically return an 403 if it fails the update method in our policy above.

So that's all gates are! Permissions. Nothing scary. But these days I exclusively use Policy classes, as well as Spatie's Laravel Permissions package.

Happy coding šŸ„³

Ā 
Share this