{"id":236,"date":"2025-08-27T14:12:00","date_gmt":"2025-08-27T14:12:00","guid":{"rendered":"https:\/\/1v0.net\/blog\/?p=236"},"modified":"2025-08-27T14:12:03","modified_gmt":"2025-08-27T14:12:03","slug":"how-to-manage-permissions-in-laravel-without-coding","status":"publish","type":"post","link":"https:\/\/1v0.net\/blog\/how-to-manage-permissions-in-laravel-without-coding\/","title":{"rendered":"How to Manage Permissions in Laravel Without Coding"},"content":{"rendered":"\n<p>Managing permissions directly in code works fine for developers, but in real projects, you\u2019ll often want <strong>non-developers (like team managers or admins)<\/strong> to control who can do what. Instead of hardcoding permissions, Laravel + Spatie Permissions lets you store them in the database and even manage them through a user-friendly interface.<\/p>\n\n\n\n<p>In this guide, we\u2019ll build a <strong>permissions management system in Laravel 12<\/strong> that doesn\u2019t require writing PHP code. Admins will be able to create new permissions, assign them to roles, and give or revoke permissions from users directly from the UI.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1 &#8211; Prerequisites<\/strong><\/h2>\n\n\n\n<p>Before continuing, make sure you have followed our <a href=\"\/blog\/laravel-spatie-permissions-step-by-step-installation-setup\">Spatie Permissions setup guide<\/a>. You should already have the required migrations, <code>User<\/code> model updated with the <code>HasRoles<\/code> trait, and some roles seeded.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2 &#8211; Storing Permissions in the Database<\/strong><\/h2>\n\n\n\n<p>With Spatie, permissions are stored in the <code>permissions<\/code> table. This means you don\u2019t need to update your codebase when you want to add new ones \u2014 you just insert rows into the table.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">INSERT INTO permissions (name, guard_name, created_at, updated_at)\nVALUES (<span class=\"hljs-string\">'approve comments'<\/span>, <span class=\"hljs-string\">'web'<\/span>, NOW(), NOW());<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This creates a new permission named <code>approve comments<\/code>. Once created, you can assign it to roles or users dynamically without modifying your PHP files.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3 &#8211; Building a Permissions Management UI<\/strong><\/h2>\n\n\n\n<p>Let\u2019s create a simple UI where admins can add new permissions, assign them to roles, and manage them without coding.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ routes\/web.php<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>\\<span class=\"hljs-title\">Admin<\/span>\\<span class=\"hljs-title\">PermissionController<\/span>;\n\nRoute::middleware(&#91;<span class=\"hljs-string\">'auth'<\/span>,<span class=\"hljs-string\">'role:admin'<\/span>])-&gt;group(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n    Route::resource(<span class=\"hljs-string\">'\/admin\/permissions'<\/span>, PermissionController::class);\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Generate the controller:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">php artisan make:controller Admin\/PermissionController --resource<\/code><\/span><\/pre>\n\n\n<p>Controller logic (<code>app\/Http\/Controllers\/Admin\/PermissionController.php<\/code>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>\\<span class=\"hljs-title\">Admin<\/span>;\n\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>\\<span class=\"hljs-title\">Controller<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Request<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Spatie<\/span>\\<span class=\"hljs-title\">Permission<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">Permission<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PermissionController<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Controller<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">index<\/span><span class=\"hljs-params\">()<\/span>\n    <\/span>{\n        $permissions = Permission::all();\n        <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'admin.permissions.index'<\/span>, compact(<span class=\"hljs-string\">'permissions'<\/span>));\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">create<\/span><span class=\"hljs-params\">()<\/span>\n    <\/span>{\n        <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'admin.permissions.create'<\/span>);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">store<\/span><span class=\"hljs-params\">(Request $request)<\/span>\n    <\/span>{\n        $request-&gt;validate(&#91;\n            <span class=\"hljs-string\">'name'<\/span> =&gt; <span class=\"hljs-string\">'required|unique:permissions,name'<\/span>\n        ]);\n\n        Permission::create(&#91;<span class=\"hljs-string\">'name'<\/span> =&gt; $request-&gt;name]);\n        <span class=\"hljs-keyword\">return<\/span> redirect()-&gt;route(<span class=\"hljs-string\">'permissions.index'<\/span>)-&gt;with(<span class=\"hljs-string\">'status'<\/span>,<span class=\"hljs-string\">'Permission created!'<\/span>);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">edit<\/span><span class=\"hljs-params\">(Permission $permission)<\/span>\n    <\/span>{\n        <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'admin.permissions.edit'<\/span>, compact(<span class=\"hljs-string\">'permission'<\/span>));\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">update<\/span><span class=\"hljs-params\">(Request $request, Permission $permission)<\/span>\n    <\/span>{\n        $request-&gt;validate(&#91;\n            <span class=\"hljs-string\">'name'<\/span> =&gt; <span class=\"hljs-string\">'required|unique:permissions,name,'<\/span>.$permission-&gt;id\n        ]);\n\n        $permission-&gt;update(&#91;<span class=\"hljs-string\">'name'<\/span> =&gt; $request-&gt;name]);\n        <span class=\"hljs-keyword\">return<\/span> redirect()-&gt;route(<span class=\"hljs-string\">'permissions.index'<\/span>)-&gt;with(<span class=\"hljs-string\">'status'<\/span>,<span class=\"hljs-string\">'Permission updated!'<\/span>);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">destroy<\/span><span class=\"hljs-params\">(Permission $permission)<\/span>\n    <\/span>{\n        $permission-&gt;delete();\n        <span class=\"hljs-keyword\">return<\/span> redirect()-&gt;route(<span class=\"hljs-string\">'permissions.index'<\/span>)-&gt;with(<span class=\"hljs-string\">'status'<\/span>,<span class=\"hljs-string\">'Permission deleted!'<\/span>);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Example Blade view (<code>resources\/views\/admin\/permissions\/index.blade.php<\/code>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">@extends('layouts.app')\n\n@section('content')\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Permissions<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"{{ route('permissions.create') }}\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"btn btn-primary mb-3\"<\/span>&gt;<\/span>Add Permission<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">table<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"table table-bordered\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">thead<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tr<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">th<\/span>&gt;<\/span>Name<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">th<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">th<\/span>&gt;<\/span>Actions<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">th<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tr<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">thead<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tbody<\/span>&gt;<\/span>\n      @foreach($permissions as $permission)\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tr<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td<\/span>&gt;<\/span>{{ $permission-&gt;name }}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">td<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"{{ route('permissions.edit',$permission) }}\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"btn btn-sm btn-outline-secondary\"<\/span>&gt;<\/span>Edit<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">action<\/span>=<span class=\"hljs-string\">\"{{ route('permissions.destroy',$permission) }}\"<\/span> <span class=\"hljs-attr\">method<\/span>=<span class=\"hljs-string\">\"POST\"<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"display:inline\"<\/span>&gt;<\/span>\n            @csrf\n            @method('DELETE')\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"btn btn-sm btn-outline-danger\"<\/span>&gt;<\/span>Delete<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">td<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tr<\/span>&gt;<\/span>\n      @endforeach\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tbody<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">table<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n@endsection<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This interface allows an admin to add, edit, and delete permissions directly in the browser \u2014 no code required.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>4 &#8211; Assign Permissions to Roles from the UI<\/strong><\/h2>\n\n\n\n<p>You can expand the UI to let admins attach permissions to roles. Example controller snippet:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ In RoleController@edit<\/span>\n$permissions = Permission::all();\n<span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'admin.roles.edit'<\/span>, compact(<span class=\"hljs-string\">'role'<\/span>,<span class=\"hljs-string\">'permissions'<\/span>));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then in your view, simply render checkboxes for each permission, and use <code>$role-&gt;syncPermissions($request-&gt;permissions)<\/code> in your controller to save updates.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>5 &#8211; Enforcing Permissions on Controllers (Without Coding)<\/strong><\/h2>\n\n\n\n<p>Creating permissions is only half the story \u2014 we must apply them to specific pages or actions. To keep this \u201cno-code\u201d, we\u2019ll store permission-to-route mappings in the database and enforce them with a middleware.<\/p>\n\n\n\n<p>First, create a migration for a new table to store route-permission pairs:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">php<\/span> <span class=\"hljs-selector-tag\">artisan<\/span> <span class=\"hljs-selector-tag\">make<\/span><span class=\"hljs-selector-pseudo\">:migration<\/span> <span class=\"hljs-selector-tag\">create_route_permissions_table<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ database\/migrations\/xxxx_xx_xx_create_route_permissions_table.php<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Database<\/span>\\<span class=\"hljs-title\">Migrations<\/span>\\<span class=\"hljs-title\">Migration<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Database<\/span>\\<span class=\"hljs-title\">Schema<\/span>\\<span class=\"hljs-title\">Blueprint<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Support<\/span>\\<span class=\"hljs-title\">Facades<\/span>\\<span class=\"hljs-title\">Schema<\/span>;\n\n<span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Migration<\/span> <\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">up<\/span><span class=\"hljs-params\">()<\/span>: <span class=\"hljs-title\">void<\/span> <\/span>{\n        Schema::create(<span class=\"hljs-string\">'route_permissions'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">(Blueprint $table)<\/span> <\/span>{\n            $table-&gt;id();\n            $table-&gt;string(<span class=\"hljs-string\">'route_name'<\/span>);\n            $table-&gt;string(<span class=\"hljs-string\">'permission_name'<\/span>);\n            $table-&gt;timestamps();\n        });\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">down<\/span><span class=\"hljs-params\">()<\/span>: <span class=\"hljs-title\">void<\/span> <\/span>{\n        Schema::dropIfExists(<span class=\"hljs-string\">'route_permissions'<\/span>);\n    }\n};<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This table will store which permission is required for which named route.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>6 &#8211; Create a Middleware to Enforce DB Permissions<\/strong><\/h2>\n\n\n\n<p>Next, build a middleware that checks the current route against the database and ensures the logged-in user has the required permission.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">php<\/span> <span class=\"hljs-selector-tag\">artisan<\/span> <span class=\"hljs-selector-tag\">make<\/span><span class=\"hljs-selector-pseudo\">:middleware<\/span> <span class=\"hljs-selector-tag\">DynamicPermissionMiddleware<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ app\/Http\/Middleware\/DynamicPermissionMiddleware.php<\/span>\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Middleware<\/span>;\n\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Closure<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Request<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Support<\/span>\\<span class=\"hljs-title\">Facades<\/span>\\<span class=\"hljs-title\">Route<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">RoutePermission<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">DynamicPermissionMiddleware<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">handle<\/span><span class=\"hljs-params\">(Request $request, Closure $next)<\/span>\n    <\/span>{\n        $routeName = Route::currentRouteName();\n\n        $mapping = RoutePermission::where(<span class=\"hljs-string\">'route_name'<\/span>, $routeName)-&gt;first();\n\n        <span class=\"hljs-keyword\">if<\/span> ($mapping &amp;&amp; ! $request-&gt;user()?-&gt;can($mapping-&gt;permission_name)) {\n            abort(<span class=\"hljs-number\">403<\/span>, <span class=\"hljs-string\">'You do not have permission to access this page.'<\/span>);\n        }\n\n        <span class=\"hljs-keyword\">return<\/span> $next($request);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Register this middleware in <code>app\/Http\/Kernel.php<\/code> under <code>$routeMiddleware<\/code> as <code>'dynamic.permission'<\/code>.<\/p>\n\n\n\n<p>Now, any route using this middleware will check its required permission dynamically from the database.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>7 &#8211; Admin UI to Map Routes to Permissions<\/strong><\/h2>\n\n\n\n<p>Finally, let\u2019s give admins the power to assign which permission protects which route \u2014 all from the UI.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ routes\/web.php<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>\\<span class=\"hljs-title\">Admin<\/span>\\<span class=\"hljs-title\">RoutePermissionController<\/span>;\n\nRoute::middleware(&#91;<span class=\"hljs-string\">'auth'<\/span>,<span class=\"hljs-string\">'role:admin'<\/span>])-&gt;group(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n    Route::resource(<span class=\"hljs-string\">'\/admin\/route-permissions'<\/span>, RoutePermissionController::class);\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Controller (<code>app\/Http\/Controllers\/Admin\/RoutePermissionController.php<\/code>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>\\<span class=\"hljs-title\">Admin<\/span>;\n\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>\\<span class=\"hljs-title\">Controller<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Request<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">RoutePermission<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Spatie<\/span>\\<span class=\"hljs-title\">Permission<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">Permission<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Support<\/span>\\<span class=\"hljs-title\">Facades<\/span>\\<span class=\"hljs-title\">Route<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">RoutePermissionController<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Controller<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">index<\/span><span class=\"hljs-params\">()<\/span>\n    <\/span>{\n        $routes = collect(Route::getRoutes())-&gt;pluck(<span class=\"hljs-string\">'action.as'<\/span>)-&gt;filter();\n        $permissions = Permission::all();\n        $mappings = RoutePermission::all();\n\n        <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'admin.route-permissions.index'<\/span>, compact(<span class=\"hljs-string\">'routes'<\/span>,<span class=\"hljs-string\">'permissions'<\/span>,<span class=\"hljs-string\">'mappings'<\/span>));\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">store<\/span><span class=\"hljs-params\">(Request $request)<\/span>\n    <\/span>{\n        RoutePermission::updateOrCreate(\n            &#91;<span class=\"hljs-string\">'route_name'<\/span> =&gt; $request-&gt;route_name],\n            &#91;<span class=\"hljs-string\">'permission_name'<\/span> =&gt; $request-&gt;permission_name]\n        );\n\n        <span class=\"hljs-keyword\">return<\/span> redirect()-&gt;back()-&gt;with(<span class=\"hljs-string\">'status'<\/span>,<span class=\"hljs-string\">'Mapping saved!'<\/span>);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Blade view (<code>resources\/views\/admin\/route-permissions\/index.blade.php<\/code>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">@extends('layouts.app')\n\n@section('content')\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Route-Permission Mappings<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">method<\/span>=<span class=\"hljs-string\">\"POST\"<\/span> <span class=\"hljs-attr\">action<\/span>=<span class=\"hljs-string\">\"{{ route('route-permissions.store') }}\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mb-4\"<\/span>&gt;<\/span>\n    @csrf\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mb-3\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span>&gt;<\/span>Route<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"route_name\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-select\"<\/span>&gt;<\/span>\n        @foreach($routes as $route)\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"{{ $route }}\"<\/span>&gt;<\/span>{{ $route }}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n        @endforeach\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mb-3\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span>&gt;<\/span>Permission<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"permission_name\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-select\"<\/span>&gt;<\/span>\n        @foreach($permissions as $permission)\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"{{ $permission-&gt;name }}\"<\/span>&gt;<\/span>{{ $permission-&gt;name }}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n        @endforeach\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"btn btn-primary\"<\/span>&gt;<\/span>Save Mapping<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span>&gt;<\/span>Existing Mappings<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n    @foreach($mappings as $map)\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span>Route: {{ $map-&gt;route_name }} \u2192 Permission: {{ $map-&gt;permission_name }}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n    @endforeach\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n@endsection<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, an admin can log into the UI, select a route (by name), and choose which permission is required. The middleware enforces it automatically \u2014 without writing any PHP code.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>We built a <strong>permissions management UI in Laravel 12<\/strong> that lets admins create, update, and delete permissions directly from the browser. By storing permissions in the database and exposing them via an admin panel, you empower non-developers to control application access without touching code. This makes your app far more flexible and team-friendly.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">What\u2019s Next<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/blog\/how-to-give-and-revoke-permissions-to-users-in-laravel\">How to Give and Revoke Permissions to Users in Laravel<\/a><\/li>\n<li><a href=\"\/blog\/creating-a-user-friendly-roles-permissions-ui-in-laravel\">Creating a User-Friendly Roles &amp; Permissions UI in Laravel<\/a><\/li>\n<li><a href=\"\/blog\/laravel-middleware-for-role-based-route-protection\">Laravel Middleware for Role-Based Route Protection<\/a><\/li>\n<\/ul>\n\n","protected":false},"excerpt":{"rendered":"<p>Managing permissions directly in code works fine for developers, but in real projects, you\u2019ll often want non-developers (like team managers or admins) to control who can do what. Instead of hardcoding permissions, Laravel + Spatie Permissions lets you store them in the database and even manage them through a user-friendly interface. In this guide, we\u2019ll [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":240,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[23,12,16,15,17,32],"class_list":["post-236","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","tag-access-control","tag-authentication","tag-permissions","tag-roles","tag-roles-and-permissions","tag-spatie"],"_links":{"self":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/236","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/comments?post=236"}],"version-history":[{"count":1,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/236\/revisions"}],"predecessor-version":[{"id":239,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/236\/revisions\/239"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media?parent=236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/categories?post=236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/tags?post=236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}