A Rapid Introduction to Laravel Gates

March 15, 2023
Written by
Temitope Taiwo Oyedele
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by

A rapid introduction to Laravel Gates

Laravel provides a wide range of features that make web development faster and more efficient. And one of the essential features of web development is authorization. In this article, we'll talk about one of the key authorize features: Gates.

Prerequisites

To follow along with this tutorial, you must have:

What is authorization?

Authorization is the process of determining whether a user has access to a specific resource or not. This resource could be anything, such as a web page, a file, or a database record. Authorization is a crucial aspect of web application security and ensures that users can only access the resources they are authorized to access.

Laravel Authorization

Laravel provides a powerful and flexible authorization system that allows developers to control access to resources based on various criteria. The Laravel authorization system is based on Gates and Policies. Our focus will be on Gates in this article.

What are Laravel Gates?

Laravel Gates are a way to manage authorization in Laravel. Gates are closures that decide whether or not a user is allowed to perform a given action and are typically defined in the app/providers/AuthServiceProvider class using the Gate facade, which provides methods for defining and checking Gates. For example, you could create a Gate that only allows users with administrative privileges to access certain pages or features of your application.

How to Define a Laravel Gate

To define a Gate in Laravel, we use the Gate::define() method. This method takes two arguments, the name of the gate, and a callback function that defines the Gate's logic. The callback function should return a boolean value indicating whether the user is authorized to access the resource.

For example, we can define a Gate that checks if the user is an administrator as follows:

use Illuminate\Support\Facades\Gate;

Gate::define('admin', function ($user) {
    return $user->isAdmin();
});

In the code above, the admin Gate checks whether the user is an admin by calling the isAdmin() method on the user model. If the method returns true, the Gate allows access; otherwise, access is denied.

Checking a Gate

To check if a user is permitted or authorized to access a resource, we can use the Gate::allows() method. This method takes two arguments: the name of the Gate, and any additional parameters required by the Gate's callback function.

For example, to check the admin Gate:

if (Gate::allows('admin')) {
    // User is authorized
} else {
    // User is not authorized
}

In the code above, we check if the user is authorized to access the admin Gate. If the Gate allows access, we can perform any necessary actions. If access is denied, we can display an error message or redirect the user to a different page.

Using Additional Parameters

Gates can also accept additional parameters to provide more context for the authorization decision. In the following example, we can define a Gate that checks if a user is the owner of a particular resource:

use Illuminate\Support\Facades\Gate;

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

Here, the update-post Gate checks if the user is the owner of the post by comparing the user's ID to the post's user_id attribute.

To check if the user is authorized to update a particular post, we can pass both the user and the post to the allows() method, as in the following example:

if (Gate::allows('update-post', [$user, $post])) {
    // User is authorized to update the post
} else {
    // User is not authorized to update the post
}

When to use Gates

Role-based access control: Laravel Gates can be used to restrict access to specific parts of a web application based on the user's role. For example, you may want to restrict access to certain administrative features to users with an "admin" role.

Resource ownership: Laravel Gates can be used to restrict access to resources based on ownership. For example, you may want to restrict access to a user's own profile page or restrict editing of a specific post to only the user who created it.

Custom business logic: Laravel Gates can be used to enforce custom business logic based on the specific needs of your web application. For example, you may want to restrict access to a specific feature based on whether a user has made a certain number of purchases or has a specific subscription level.

Now, let's step through an example.

Configure your database

The first thing we’ll do is configure our database for this example. To configure the database, simply locate a file called .env in our Laravel project. We’ll then connect our database by setting the following credentials.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME= your_database_username
DB_PASSWORD=

Replace your_database_name with the actual name of your database and your_database_username with root.

If you’re just creating your database, run the database migrations, after following the steps above, by running the following command:

php artisan migrate

Define a Gate

Suppose you have a website and want to show content only subscribers can access. So how, then, will you restrict users and only grant access to subscribers only?

Let’s add another field in the users table called subs, short for "subscribers". It will be a boolean. The subs will be given a value of 0 for users who don’t subscribe and 1 for users who subscribe.

To do this, run the following Artisan command to generate a new migration file:

php artisan make:migration add_subs_to_users_table --table=users

Next, open the newly created migration file located at database/migrations/<timestamp>_add_subs_to_users_table.php and modify the up() method like so:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->boolean('subs')->default(0);
    });
}

Now, run the migration using the migrate Artisan command:

php artisan migrate

Doing this will add a new subs field to the users table as a boolean field with a default value of 0.

Lastly, we’ll update the default value of the subs field for a given user. To do that, open the database in your database tool of choice, in the users table, set the subs column to 1 for your desired user.

Now let’s proceed with our project.

What we want to achieve is that when a user is subscribed, an extra link will appear alongside the "home" link when the user clicks the "Laravel" link, after, after the user logs in. This link will be visible to the users who have subscribed to view the content.

So the first thing we’ll be adding is the link. To achieve this, navigate to resources/views/welcome.blade.php, and right below our homepage link, we’ll add this:

&sol; <a href="{{ url('/subs') }}"
    class="font-semibold text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500">Subscribers</a>

Let’s now create our subs route. Inside our route/web.php, include this right after our welcome routes:

Route::get('subs',function(){
     return view('subs');
});

The next thing to do is to create a view called subs.blade.php in resources/views.This will be content that we'll display to our subscribers. In the file, add the following:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Restricted Content</title>
        <!-- Styles -->
        <style>
            /* ! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com */*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::after,::before{--tw-content:''}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:Figtree, sans-serif;font-feature-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*, ::before, ::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::-webkit-backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.relative{position:relative}.mx-auto{margin-left:auto;margin-right:auto}.mx-6{margin-left:1.5rem;margin-right:1.5rem}.ml-4{margin-left:1rem}.mt-16{margin-top:4rem}.mt-6{margin-top:1.5rem}.mt-4{margin-top:1rem}.-mt-px{margin-top:-1px}.mr-1{margin-right:0.25rem}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.h-16{height:4rem}.h-7{height:1.75rem}.h-6{height:1.5rem}.h-5{height:1.25rem}.min-h-screen{min-height:100vh}.w-auto{width:auto}.w-16{width:4rem}.w-7{width:1.75rem}.w-6{width:1.5rem}.w-5{width:1.25rem}.max-w-7xl{max-width:80rem}.shrink-0{flex-shrink:0}.scale-100{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.grid-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr))}.items-center{align-items:center}.justify-center{justify-content:center}.gap-6{gap:1.5rem}.gap-4{gap:1rem}.self-center{align-self:center}.rounded-lg{border-radius:0.5rem}.rounded-full{border-radius:9999px}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246 / var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242 / var(--tw-bg-opacity))}.bg-dots-darker{background-image:url("data:image/svg+xml,%3Csvg width='30' height='30' viewBox='0 0 30 30' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1.22676 0C1.91374 0 2.45351 0.539773 2.45351 1.22676C2.45351 1.91374 1.91374 2.45351 1.22676 2.45351C0.539773 2.45351 0 1.91374 0 1.22676C0 0.539773 0.539773 0 1.22676 0Z' fill='rgba(0,0,0,0.07)'/%3E%3C/svg%3E")}.from-gray-700\/50{--tw-gradient-from:rgb(55 65 81 / 0.5);--tw-gradient-to:rgb(55 65 81 / 0);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.via-transparent{--tw-gradient-to:rgb(0 0 0 / 0);--tw-gradient-stops:var(--tw-gradient-from), transparent, var(--tw-gradient-to)}.bg-center{background-position:center}.stroke-red-500{stroke:#ef4444}.stroke-gray-400{stroke:#9ca3af}.p-6{padding:1.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.text-center{text-align:center}.text-right{text-align:right}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-sm{font-size:0.875rem;line-height:1.25rem}.font-semibold{font-weight:600}.leading-relaxed{line-height:1.625}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99 / var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128 / var(--tw-text-opacity))}.underline{-webkit-text-decoration-line:underline;text-decoration-line:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgb(0 0 0 / 0.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}.shadow-gray-500\/20{--tw-shadow-color:rgb(107 114 128 / 0.2);--tw-shadow:var(--tw-shadow-colored)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms}.selection\:bg-red-500 *::selection{--tw-bg-opacity:1;background-color:rgb(239 68 68 / var(--tw-bg-opacity))}.selection\:text-white *::selection{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity))}.selection\:bg-red-500::selection{--tw-bg-opacity:1;background-color:rgb(239 68 68 / var(--tw-bg-opacity))}.selection\:text-white::selection{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39 / var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81 / var(--tw-text-opacity))}.focus\:rounded-sm:focus{border-radius:0.125rem}.focus\:outline:focus{outline-style:solid}.focus\:outline-2:focus{outline-width:2px}.focus\:outline-red-500:focus{outline-color:#ef4444}.group:hover .group-hover\:stroke-gray-600{stroke:#4b5563}@media (prefers-reduced-motion: no-preference){.motion-safe\:hover\:scale-\[1\.01\]:hover{--tw-scale-x:1.01;--tw-scale-y:1.01;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}}@media (prefers-color-scheme: dark){.dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39 / var(--tw-bg-opacity))}.dark\:bg-gray-800\/50{background-color:rgb(31 41 55 / 0.5)}.dark\:bg-red-800\/20{background-color:rgb(153 27 27 / 0.2)}.dark\:bg-dots-lighter{background-image:url("data:image/svg+xml,%3Csvg width='30' height='30' viewBox='0 0 30 30' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1.22676 0C1.91374 0 2.45351 0.539773 2.45351 1.22676C2.45351 1.91374 1.91374 2.45351 1.22676 2.45351C0.539773 2.45351 0 1.91374 0 1.22676C0 0.539773 0.539773 0 1.22676 0Z' fill='rgba(255,255,255,0.07)'/%3E%3C/svg%3E")}.dark\:bg-gradient-to-bl{background-image:linear-gradient(to bottom left, var(--tw-gradient-stops))}.dark\:stroke-gray-600{stroke:#4b5563}.dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175 / var(--tw-text-opacity))}.dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity))}.dark\:shadow-none{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}.dark\:ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)}.dark\:ring-inset{--tw-ring-inset:inset}.dark\:ring-white\/5{--tw-ring-color:rgb(255 255 255 / 0.05)}.dark\:hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity))}.group:hover .dark\:group-hover\:stroke-gray-400{stroke:#9ca3af}}@media (min-width: 640px){.sm\:fixed{position:fixed}.sm\:top-0{top:0px}.sm\:right-0{right:0px}.sm\:ml-0{margin-left:0px}.sm\:flex{display:flex}.sm\:items-center{align-items:center}.sm\:justify-center{justify-content:center}.sm\:justify-between{justify-content:space-between}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width: 768px){.md\:grid-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr))}}@media (min-width: 1024px){.lg\:gap-8{gap:2rem}.lg\:p-8{padding:2rem}}
        </style>
</head>
<body class="antialiased">
<div class="relative sm:flex sm:justify-center sm:items-center min-h-screen bg-dots-darker bg-center bg-gray-100 dark:bg-dots-lighter dark:bg-gray-900 selection:bg-red-500 selection:text-white">
        <h1 class="text-4xl font-semibold text-gray-900 dark:text-white">You are subscribed to this channel so you can view this content</h1>
</div>
</body>
</html>

Next, we need to restrict this page from being accessed by users who didn't subscribe. Now, this is where our Gate comes in. To do this, we’ll first define our Gate. Inside app/providers/AuthServiceProvider.php, uncomment use Illuminate\Support\Facades\Gate; or add it to the file if it is missing, then define the Gate by adding this inside the boot() method:

Gate::define('subs-only', function($user) {
    If ($user->subs ==1) {
        return true;
    }
    return false;
});

In the code above, the Gate::define() method takes two parameters: the name of the gate being defined, which is called subs-only and a closure that implements the gate's authorization logic.

The closure takes a single parameter, $user, which represents the user being checked for access. The closure checks if the user's subs property is equal to 1. If the user has a subscription, the function returns true, indicating that the user is authorized to access the resource or perform the action. Otherwise, it returns false, indicating that the user is not authorized.

For better understanding, the boot() method now looks like this:

public function boot()
{
    $this->registerPolicies();
       
    Gate::define('subs-only', function($user) {
        if($user->subs === 1) {
            return true;
        }
        return false;
    });
}

Here, we named our Gate subs-only.It will get our user details.

The next thing is to restrict our users from having access to the content if they haven't subscribed. We need to authorize the actions and use the allow() method. To do this, let’s go back to routes/web.php and modify the code to match the following:

Route::get('subs',function() {
    if (Gate::allows('subs-only', Auth::user())) {
          return view('subs');
    }
});

The code above checks if the authenticated user can access the "subs" page. If so, the "subs" view is displayed.

Lastly, we'll make the link to the content only visible to the subscribers as this will make it more efficient instead of showing us something like "you are not authorized to view this". Go back to resources/views/welcome.blade.php and wrap our link inside the @can directive, as in the following code.

@can('subs-only', Auth::user())
    <a href="{{ url('/subs') }}" 
         class="text-sm text-gray-700 dark:text-gray-500 underline">Subscribers</a>
@endcan

In the code above, we check if the authenticated user has the "subs-only" permission using the @can directive. Our link will not be displayed if the authenticated user does not have the subs-only permission.

All done! Now here's a summary of everything we did and what we want to happen:

  • We created content that we wanted to show to only our subscribed users.
  • We used the @can('subs-only', Auth::user()) to check if the currently authenticated user has permission.
  • We created a link and made it only visible to the subscriber alone. This was possible by using gates which helped us restrict the content to only authorized users.

Test that the application works

Now, let’s run our code and see the changes working. First, start the application by running the command below.

php artisan serve

Then, open http://localhost:8000 in your browser of choice (change the port if it is bound to a different port) and click Login in the top right corner. After logging in, click the Laravel link. You'll now see the new Subscribers link appear next to the Home link, as in the animation below.

Logging in to the Laravel application as a subscribed user and seeing the Subscribers link appear.

Here’s what happens when a user who is not subscribed logs in. You can see that the new link does not appear.

Logging in to the Laravel application as an unsubscribed user and not seeing the Subscribers link appear.

And that’s a wrap, everyone!

Conclusion

In this article, we talked about authorization and how it works. We also discussed Gates as a method of authorization, while also sighting an example of how to use it.

Laravel Gates are a powerful way to manage authorization in Laravel. By defining simple PHP functions that determine what actions a user can perform, you can easily control access to your application's resources and features. Whether you're building a simple website or a complex web application, Laravel Gates are a valuable tool to have in your toolkit.

In the next part, we'll take a look at policies. Please share if you found it helpful.

Temitope Taiwo Oyedele is a software developer and technical writer. He likes to write about things he’s learned and experienced.