{"id":133,"date":"2025-08-25T19:15:38","date_gmt":"2025-08-25T19:15:38","guid":{"rendered":"https:\/\/1v0.net\/blog\/?p=133"},"modified":"2025-08-26T08:50:13","modified_gmt":"2025-08-26T08:50:13","slug":"creating-a-user-friendly-roles-permissions-ui-in-laravel","status":"publish","type":"post","link":"https:\/\/1v0.net\/blog\/creating-a-user-friendly-roles-permissions-ui-in-laravel\/","title":{"rendered":"Creating a User-Friendly Roles &#038; Permissions UI in Laravel"},"content":{"rendered":"\n<p>Roles make high-level access control simple, but sometimes you need finer control: specific users may need one or two extra abilities without changing their whole role. That\u2019s where a clean, admin-friendly <strong>Permissions UI<\/strong> helps. In this guide, you\u2019ll create a user-friendly interface in Laravel 12 to manage roles and permissions, assign <em>both roles and individual permissions<\/em> to users, and protect pages using either roles or permissions.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>First, make sure your app has basic authentication so only logged-in users can access the Roles &amp; Permissions UI. If you don\u2019t want to use Fortify or Breeze, you can build lightweight login and registration forms as shown in our <em>\u201c<a href=\"https:\/\/1v0.net\/blog\/how-to-add-authentication-in-laravel-12-without-fortify\/\" data-type=\"post\" data-id=\"126\">Authentication in Laravel 12 (Without Fortify)<\/a>\u201d<\/em> article.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>When building the forms for creating roles or permissions, you\u2019ll want to validate the inputs properly. See <a href=\"https:\/\/1v0.net\/blog\/mastering-validation-rules-in-laravel-12\/\" data-type=\"post\" data-id=\"129\">Mastering Validation Rules in Laravel 12<\/a> for a deep dive into handling validation cleanly.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>For a bigger picture of how roles and permissions fit into a complete app, you may also enjoy: <a href=\"https:\/\/1v0.net\/blog\/step-by-step-guide-creating-a-user-roles-and-permissions-app-with-laravel-12\/\" data-type=\"post\" data-id=\"115\">Step-by-Step Guide: Creating a User Roles and Permissions App with Laravel 12.<\/a><\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>For simplicity, assume you have a working <code>\/login<\/code> and <code>\/register<\/code> system, with users stored in the <code>users<\/code> table.<\/p>\n\n\n\n<p><\/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: Install &amp; Configure Spatie<\/strong><\/h2>\n\n\n\n<p><\/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\">composer <span class=\"hljs-built_in\">require<\/span> spatie\/laravel-permission\nphp artisan vendor:publish --provider=<span class=\"hljs-string\">\"Spatie\\Permission\\PermissionServiceProvider\"<\/span>\nphp artisan migrate<\/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<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>This installs tables for <code>roles<\/code>, <code>permissions<\/code>, and their relationships. Add the trait to your <code>User<\/code> model:<\/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\">\/\/ app\/Models\/User.php<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Spatie<\/span>\\<span class=\"hljs-title\">Permission<\/span>\\<span class=\"hljs-title\">Traits<\/span>\\<span class=\"hljs-title\">HasRoles<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">User<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Authenticatable<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">HasRoles<\/span>;\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>All users can now be given roles and\/or individual permissions through code or the UI we\u2019ll build next.<\/p>\n\n\n\n<p><\/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; Admin Routes (Roles + Permissions + Assignments)<\/strong><\/h2>\n\n\n\n<p><\/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 shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ routes\/web.php<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><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\">RoleController<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><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<\/span><\/span><span class='shcb-loc'><span><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\">UserRoleController<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><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\">UserPermissionController<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ Admin-only area<\/span>\n<\/span><\/span><span class='shcb-loc'><span>Route::middleware(&#91;<span class=\"hljs-string\">'auth'<\/span>, <span class=\"hljs-string\">'role:Admin'<\/span>])-&gt;prefix(<span class=\"hljs-string\">'admin'<\/span>)-&gt;name(<span class=\"hljs-string\">'admin.'<\/span>)-&gt;group(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    Route::resource(<span class=\"hljs-string\">'roles'<\/span>, RoleController::class);               <span class=\"hljs-comment\">\/\/ CRUD roles<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    Route::resource(<span class=\"hljs-string\">'permissions'<\/span>, PermissionController::class);   <span class=\"hljs-comment\">\/\/ CRUD permissions<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ Assign roles to users<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    Route::get(<span class=\"hljs-string\">'users\/{user}\/roles'<\/span>, &#91;UserRoleController::class, <span class=\"hljs-string\">'edit'<\/span>])-&gt;name(<span class=\"hljs-string\">'users.roles.edit'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    Route::put(<span class=\"hljs-string\">'users\/{user}\/roles'<\/span>, &#91;UserRoleController::class, <span class=\"hljs-string\">'update'<\/span>])-&gt;name(<span class=\"hljs-string\">'users.roles.update'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ Assign permissions directly to users<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    Route::get(<span class=\"hljs-string\">'users\/{user}\/permissions'<\/span>, &#91;UserPermissionController::class, <span class=\"hljs-string\">'edit'<\/span>])-&gt;name(<span class=\"hljs-string\">'users.permissions.edit'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    Route::put(<span class=\"hljs-string\">'users\/{user}\/permissions'<\/span>, &#91;UserPermissionController::class, <span class=\"hljs-string\">'update'<\/span>])-&gt;name(<span class=\"hljs-string\">'users.permissions.update'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>});\n<\/span><\/span><\/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>These routes provide separate screens to manage roles, manage permissions, and assign either to users. Everything is under <code>auth<\/code> + <code>role:Admin<\/code> to keep it safe.<\/p>\n\n\n\n<p><\/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; Permissions Management UI (CRUD)<\/strong><\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Create a simple page where admins can add\/delete permissions. Keep names consistent like <code>posts.create<\/code>, <code>users.edit<\/code>, etc., so the UI stays tidy.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ app\/Http\/Controllers\/Admin\/PermissionController.php<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><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<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><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><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-class\"><\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    <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><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-function\">    <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>        $permissions = Permission::orderBy(<span class=\"hljs-string\">'name'<\/span>)-&gt;paginate(<span class=\"hljs-number\">15<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'admin.permissions.index'<\/span>, compact(<span class=\"hljs-string\">'permissions'<\/span>));\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <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><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-function\">    <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>        $data = $request-&gt;validate(&#91;\n<\/span><\/span><span class='shcb-loc'><span>            <span class=\"hljs-string\">'name'<\/span> =&gt; <span class=\"hljs-string\">'required|string|max:255|unique:permissions,name'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>        ]);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>        Permission::create(&#91;<span class=\"hljs-string\">'name'<\/span> =&gt; $data&#91;<span class=\"hljs-string\">'name'<\/span>]]);\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> back()-&gt;with(<span class=\"hljs-string\">'status'<\/span>, <span class=\"hljs-string\">'Permission created.'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <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><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-function\">    <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>        $permission-&gt;delete();\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> back()-&gt;with(<span class=\"hljs-string\">'status'<\/span>, <span class=\"hljs-string\">'Permission deleted.'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><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<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Controller actions to list, create, and delete permissions. You can add <code>edit\/update<\/code> later if you want to rename permissions (be mindful of existing assignments).<\/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\">\/\/ resources\/views\/admin\/permissions\/index.blade.php<\/span>\n\n@extends(<span class=\"hljs-string\">'layouts.app'<\/span>)\n\n@section(<span class=\"hljs-string\">'content'<\/span>)\n&lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">container<\/span>\"&gt;\n  &lt;<span class=\"hljs-title\">h2<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">mb<\/span>-4\"&gt;<span class=\"hljs-title\">Permissions<\/span>&lt;\/<span class=\"hljs-title\">h2<\/span>&gt;\n\n  @<span class=\"hljs-title\">if<\/span>(<span class=\"hljs-title\">session<\/span>('<span class=\"hljs-title\">status<\/span>')) &lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">alert<\/span> <span class=\"hljs-title\">alert<\/span>-<span class=\"hljs-title\">success<\/span>\"&gt;<\/span>{{ session(<span class=\"hljs-string\">'status'<\/span>) }}&lt;\/div&gt; @<span class=\"hljs-keyword\">endif<\/span>\n\n  &lt;form method=<span class=\"hljs-string\">\"POST\"<\/span> action=<span class=\"hljs-string\">\"{{ route('admin.permissions.store') }}\"<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">d<\/span>-<span class=\"hljs-title\">flex<\/span> <span class=\"hljs-title\">mb<\/span>-3\"&gt;\n    @<span class=\"hljs-title\">csrf<\/span>\n    &lt;<span class=\"hljs-title\">input<\/span> <span class=\"hljs-title\">type<\/span>=\"<span class=\"hljs-title\">text<\/span>\" <span class=\"hljs-title\">name<\/span>=\"<span class=\"hljs-title\">name<\/span>\" <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">form<\/span>-<span class=\"hljs-title\">control<\/span> <span class=\"hljs-title\">me<\/span>-2\" <span class=\"hljs-title\">placeholder<\/span>=\"<span class=\"hljs-title\">e<\/span>.<span class=\"hljs-title\">g<\/span>. <span class=\"hljs-title\">posts<\/span>.<span class=\"hljs-title\">publish<\/span>\" <span class=\"hljs-title\">required<\/span>&gt;\n    &lt;<span class=\"hljs-title\">button<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">btn<\/span> <span class=\"hljs-title\">btn<\/span>-<span class=\"hljs-title\">primary<\/span>\"&gt;<span class=\"hljs-title\">Add<\/span> <span class=\"hljs-title\">Permission<\/span>&lt;\/<span class=\"hljs-title\">button<\/span>&gt;\n  &lt;\/<span class=\"hljs-title\">form<\/span>&gt;\n\n  &lt;<span class=\"hljs-title\">table<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">table<\/span> <span class=\"hljs-title\">table<\/span>-<span class=\"hljs-title\">striped<\/span> <span class=\"hljs-title\">align<\/span>-<span class=\"hljs-title\">middle<\/span>\"&gt;\n    &lt;<span class=\"hljs-title\">thead<\/span>&gt;&lt;<span class=\"hljs-title\">tr<\/span>&gt;&lt;<span class=\"hljs-title\">th<\/span>&gt;<span class=\"hljs-title\">Permission<\/span>&lt;\/<span class=\"hljs-title\">th<\/span>&gt;&lt;<span class=\"hljs-title\">th<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">text<\/span>-<span class=\"hljs-title\">end<\/span>\"&gt;<span class=\"hljs-title\">Actions<\/span>&lt;\/<span class=\"hljs-title\">th<\/span>&gt;&lt;\/<span class=\"hljs-title\">tr<\/span>&gt;&lt;\/<span class=\"hljs-title\">thead<\/span>&gt;\n    &lt;<span class=\"hljs-title\">tbody<\/span>&gt;\n      @<span class=\"hljs-title\">foreach<\/span>($<span class=\"hljs-title\">permissions<\/span> <span class=\"hljs-title\">as<\/span> $<span class=\"hljs-title\">permission<\/span>)\n        &lt;<span class=\"hljs-title\">tr<\/span>&gt;\n          &lt;<span class=\"hljs-title\">td<\/span>&gt;<\/span>{{ $permission-&gt;name }}&lt;\/td&gt;\n          &lt;td <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">text<\/span>-<span class=\"hljs-title\">end<\/span>\"&gt;\n            &lt;<span class=\"hljs-title\">form<\/span> <span class=\"hljs-title\">action<\/span>=\"<\/span>{{ route(<span class=\"hljs-string\">'admin.permissions.destroy'<\/span>, $permission) }}<span class=\"hljs-string\">\" method=\"<\/span>POST<span class=\"hljs-string\">\" class=\"<\/span>d-inline<span class=\"hljs-string\">\"&gt;\n              @csrf @method('DELETE')\n              &lt;button class=\"<\/span>btn btn-sm btn-outline-danger<span class=\"hljs-string\">\" onclick=\"<\/span><span class=\"hljs-keyword\">return<\/span> confirm(<span class=\"hljs-string\">'Delete this permission?'<\/span>)<span class=\"hljs-string\">\"&gt;Delete&lt;\/button&gt;\n            &lt;\/form&gt;\n          &lt;\/td&gt;\n        &lt;\/tr&gt;\n      @endforeach\n    &lt;\/tbody&gt;\n  &lt;\/table&gt;\n\n  {{ $permissions-&gt;links() }}\n&lt;\/div&gt;\n@endsection<\/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>A compact index: add new permissions with a small form, list existing ones, and delete with a button. Pagination keeps the table fast and readable.<\/p>\n\n\n\n<p><\/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 Directly to a User (UI)<\/strong><\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Sometimes a user needs one-off abilities beyond their role. This screen lets an admin toggle individual permissions for a specific user.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ app\/Http\/Controllers\/Admin\/UserPermissionController.php<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><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<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">User<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">UserPermissionController<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Controller<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-class\"><\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    <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\">(User $user)<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-function\">    <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>        $permissions = Permission::orderBy(<span class=\"hljs-string\">'name'<\/span>)-&gt;get();\n<\/span><\/span><span class='shcb-loc'><span>        $user-&gt;load(<span class=\"hljs-string\">'permissions'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'admin.users.permissions'<\/span>, compact(<span class=\"hljs-string\">'user'<\/span>, <span class=\"hljs-string\">'permissions'<\/span>));\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <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, User $user)<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-function\">    <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>        $data = $request-&gt;validate(&#91;\n<\/span><\/span><span class='shcb-loc'><span>            <span class=\"hljs-string\">'permissions'<\/span> =&gt; <span class=\"hljs-string\">'array'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>        ]);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>        $user-&gt;syncPermissions($data&#91;<span class=\"hljs-string\">'permissions'<\/span>] ?? &#91;]); <span class=\"hljs-comment\">\/\/ replaces all direct perms<\/span>\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> redirect()-&gt;route(<span class=\"hljs-string\">'admin.users.permissions.edit'<\/span>, $user)-&gt;with(<span class=\"hljs-string\">'status'<\/span>, <span class=\"hljs-string\">'User permissions updated.'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><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<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>The controller loads all permissions and the user\u2019s current direct permissions. <code>syncPermissions()<\/code> replaces direct assignments in one go to keep things simple and predictable.<\/p>\n\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\">\/\/ resources\/views\/admin\/users\/permissions.blade.php<\/span>\n\n@extends(<span class=\"hljs-string\">'layouts.app'<\/span>)\n\n@section(<span class=\"hljs-string\">'content'<\/span>)\n&lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">container<\/span>\"&gt;\n  &lt;<span class=\"hljs-title\">h2<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">mb<\/span>-4\"&gt;<span class=\"hljs-title\">Direct<\/span> <span class=\"hljs-title\">Permissions<\/span>: <\/span>{{ $user-&gt;name }}&lt;\/h2&gt;\n\n  @<span class=\"hljs-keyword\">if<\/span>(session(<span class=\"hljs-string\">'status'<\/span>)) &lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">alert<\/span> <span class=\"hljs-title\">alert<\/span>-<span class=\"hljs-title\">success<\/span>\"&gt;<\/span>{{ session(<span class=\"hljs-string\">'status'<\/span>) }}&lt;\/div&gt; @<span class=\"hljs-keyword\">endif<\/span>\n\n  &lt;form method=<span class=\"hljs-string\">\"POST\"<\/span> action=<span class=\"hljs-string\">\"{{ route('admin.users.permissions.update', $user) }}\"<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">card<\/span> <span class=\"hljs-title\">card<\/span>-<span class=\"hljs-title\">body<\/span>\"&gt;\n    @<span class=\"hljs-title\">csrf<\/span> @<span class=\"hljs-title\">method<\/span>('<span class=\"hljs-title\">PUT<\/span>')\n\n    &lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">row<\/span>\"&gt;\n      @<span class=\"hljs-title\">foreach<\/span>($<span class=\"hljs-title\">permissions<\/span> <span class=\"hljs-title\">as<\/span> $<span class=\"hljs-title\">perm<\/span>)\n        &lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">col<\/span>-<span class=\"hljs-title\">md<\/span>-4 <span class=\"hljs-title\">mb<\/span>-2\"&gt;\n          &lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">form<\/span>-<span class=\"hljs-title\">check<\/span>\"&gt;\n            &lt;<span class=\"hljs-title\">input<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">form<\/span>-<span class=\"hljs-title\">check<\/span>-<span class=\"hljs-title\">input<\/span>\" <span class=\"hljs-title\">type<\/span>=\"<span class=\"hljs-title\">checkbox<\/span>\" <span class=\"hljs-title\">name<\/span>=\"<span class=\"hljs-title\">permissions<\/span>&#91;]\" <span class=\"hljs-title\">value<\/span>=\"<\/span>{{ $perm-&gt;name }}<span class=\"hljs-string\">\"\n                   id=\"<\/span>perm_{{ $perm-&gt;id }}<span class=\"hljs-string\">\" {{ $user-&gt;hasDirectPermission($perm-&gt;name) ? 'checked' : '' }}&gt;\n            &lt;label class=\"<\/span>form-check-label<span class=\"hljs-string\">\" for=\"<\/span>perm_{{ $perm-&gt;id }}<span class=\"hljs-string\">\"&gt;{{ $perm-&gt;name }}&lt;\/label&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n      @endforeach\n    &lt;\/div&gt;\n\n    &lt;div class=\"<\/span>mt<span class=\"hljs-number\">-3<\/span><span class=\"hljs-string\">\"&gt;\n      &lt;button class=\"<\/span>btn btn-success<span class=\"hljs-string\">\"&gt;Save Permissions&lt;\/button&gt;\n    &lt;\/div&gt;\n  &lt;\/form&gt;\n\n  &lt;p class=\"<\/span>text-muted mt<span class=\"hljs-number\">-3<\/span><span class=\"hljs-string\">\"&gt;\n    Tip: A user\u2019s effective permissions = direct permissions + permissions from all assigned roles.\n  &lt;\/p&gt;\n&lt;\/div&gt;\n@endsection<\/span><\/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>Checkboxes make it obvious which permissions the user has directly. The info note helps admins remember that roles also contribute permissions.<\/p>\n\n\n\n<p><\/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; (Recap) Assign Roles to a User (UI)<\/strong><\/h2>\n\n\n\n<p><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ app\/Http\/Controllers\/Admin\/UserRoleController.php<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><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<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">User<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span><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\">Role<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">UserRoleController<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Controller<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-class\"><\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    <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\">(User $user)<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-function\">    <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>        $roles = Role::orderBy(<span class=\"hljs-string\">'name'<\/span>)-&gt;get();\n<\/span><\/span><span class='shcb-loc'><span>        $user-&gt;load(<span class=\"hljs-string\">'roles'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'admin.users.roles'<\/span>, compact(<span class=\"hljs-string\">'user'<\/span>, <span class=\"hljs-string\">'roles'<\/span>));\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <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, User $user)<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-function\">    <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>        $data = $request-&gt;validate(&#91;\n<\/span><\/span><span class='shcb-loc'><span>            <span class=\"hljs-string\">'roles'<\/span> =&gt; <span class=\"hljs-string\">'array'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>        ]);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>        $user-&gt;syncRoles($data&#91;<span class=\"hljs-string\">'roles'<\/span>] ?? &#91;]); <span class=\"hljs-comment\">\/\/ replaces role set<\/span>\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> redirect()-&gt;route(<span class=\"hljs-string\">'admin.users.roles.edit'<\/span>, $user)-&gt;with(<span class=\"hljs-string\">'status'<\/span>, <span class=\"hljs-string\">'User roles updated.'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><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<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Roles are your coarse-grained access control. Keep role names short and meaningful; push complexity into permissions where needed.<\/p>\n\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\">\/\/ resources\/views\/admin\/users\/roles.blade.php<\/span>\n\n@extends(<span class=\"hljs-string\">'layouts.app'<\/span>)\n\n@section(<span class=\"hljs-string\">'content'<\/span>)\n&lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">container<\/span>\"&gt;\n  &lt;<span class=\"hljs-title\">h2<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">mb<\/span>-4\"&gt;<span class=\"hljs-title\">Assign<\/span> <span class=\"hljs-title\">Roles<\/span>: <\/span>{{ $user-&gt;name }}&lt;\/h2&gt;\n\n  @<span class=\"hljs-keyword\">if<\/span>(session(<span class=\"hljs-string\">'status'<\/span>)) &lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">alert<\/span> <span class=\"hljs-title\">alert<\/span>-<span class=\"hljs-title\">success<\/span>\"&gt;<\/span>{{ session(<span class=\"hljs-string\">'status'<\/span>) }}&lt;\/div&gt; @<span class=\"hljs-keyword\">endif<\/span>\n\n  &lt;form method=<span class=\"hljs-string\">\"POST\"<\/span> action=<span class=\"hljs-string\">\"{{ route('admin.users.roles.update', $user) }}\"<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">card<\/span> <span class=\"hljs-title\">card<\/span>-<span class=\"hljs-title\">body<\/span>\"&gt;\n    @<span class=\"hljs-title\">csrf<\/span> @<span class=\"hljs-title\">method<\/span>('<span class=\"hljs-title\">PUT<\/span>')\n\n    &lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">row<\/span>\"&gt;\n      @<span class=\"hljs-title\">foreach<\/span>($<span class=\"hljs-title\">roles<\/span> <span class=\"hljs-title\">as<\/span> $<span class=\"hljs-title\">role<\/span>)\n        &lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">col<\/span>-<span class=\"hljs-title\">md<\/span>-4 <span class=\"hljs-title\">mb<\/span>-2\"&gt;\n          &lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">form<\/span>-<span class=\"hljs-title\">check<\/span>\"&gt;\n            &lt;<span class=\"hljs-title\">input<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">form<\/span>-<span class=\"hljs-title\">check<\/span>-<span class=\"hljs-title\">input<\/span>\" <span class=\"hljs-title\">type<\/span>=\"<span class=\"hljs-title\">checkbox<\/span>\" <span class=\"hljs-title\">name<\/span>=\"<span class=\"hljs-title\">roles<\/span>&#91;]\" <span class=\"hljs-title\">value<\/span>=\"<\/span>{{ $role-&gt;name }}<span class=\"hljs-string\">\"\n                   id=\"<\/span>role_{{ $role-&gt;id }}<span class=\"hljs-string\">\" {{ $user-&gt;hasRole($role-&gt;name) ? 'checked' : '' }}&gt;\n            &lt;label class=\"<\/span>form-check-label<span class=\"hljs-string\">\" for=\"<\/span>role_{{ $role-&gt;id }}<span class=\"hljs-string\">\"&gt;{{ $role-&gt;name }}&lt;\/label&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n      @endforeach\n    &lt;\/div&gt;\n\n    &lt;div class=\"<\/span>mt<span class=\"hljs-number\">-3<\/span><span class=\"hljs-string\">\"&gt;\n      &lt;button class=\"<\/span>btn btn-success<span class=\"hljs-string\">\"&gt;Save Roles&lt;\/button&gt;\n    &lt;\/div&gt;\n  &lt;\/form&gt;\n&lt;\/div&gt;\n@endsection<\/span><\/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>UI mirrors the permissions screen to keep UX consistent: search, filter, or grouping can be added later as your list grows.<\/p>\n\n\n\n<p><\/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; Role-Protected and Permission-Protected Pages<\/strong><\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Create one page only Admins can view, and another that requires a specific permission like <code>reports.view<\/code>.<\/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 shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ routes\/web.php<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><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><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ Only users with the Admin role can access<\/span>\n<\/span><\/span><span class='shcb-loc'><span>Route::get(<span class=\"hljs-string\">'\/admin-dashboard'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'admin.dashboard'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>})-&gt;middleware(&#91;<span class=\"hljs-string\">'auth'<\/span>, <span class=\"hljs-string\">'role:Admin'<\/span>]);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ Only users who have the 'reports.view' permission (directly or via role)<\/span>\n<\/span><\/span><span class='shcb-loc'><span>Route::get(<span class=\"hljs-string\">'\/reports'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'reports.index'<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>})-&gt;middleware(&#91;<span class=\"hljs-string\">'auth'<\/span>, <span class=\"hljs-string\">'permission:reports.view'<\/span>]);\n<\/span><\/span><\/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<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Use Blade directives to show\/hide buttons and links based on role\/permission, keeping the UI aligned with access rules:<\/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-comment\">\/\/ In a Blade view<\/span>\n@role(<span class=\"hljs-string\">'Admin'<\/span>)\n  &lt;a href=<span class=\"hljs-string\">\"{{ route('admin.permissions.index') }}\"<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">btn<\/span> <span class=\"hljs-title\">btn<\/span>-<span class=\"hljs-title\">sm<\/span> <span class=\"hljs-title\">btn<\/span>-<span class=\"hljs-title\">outline<\/span>-<span class=\"hljs-title\">primary<\/span>\"&gt;<span class=\"hljs-title\">Manage<\/span> <span class=\"hljs-title\">Permissions<\/span>&lt;\/<span class=\"hljs-title\">a<\/span>&gt;\n@<span class=\"hljs-title\">endrole<\/span>\n\n@<span class=\"hljs-title\">can<\/span>('<span class=\"hljs-title\">reports<\/span>.<span class=\"hljs-title\">view<\/span>')\n  &lt;<span class=\"hljs-title\">a<\/span> <span class=\"hljs-title\">href<\/span>=\"<\/span>{{ url(<span class=\"hljs-string\">'\/reports'<\/span>) }}<span class=\"hljs-string\">\" class=\"<\/span>btn btn-primary<span class=\"hljs-string\">\"&gt;View Reports&lt;\/a&gt;\n@endcan<\/span><\/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>This keeps navigation clean: users only see what they\u2019re allowed to access, reducing confusion and accidental 403 errors.<\/p>\n\n\n\n<p><\/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; Roles Management UI (Optional Extras)<\/strong><\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>If you want roles to control their own permission sets through the UI, add an edit screen with permission checkboxes and sync them with <code>$role->syncPermissions([...])<\/code>. This lets Admins craft new roles from the browser without deployments.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>For large lists, consider adding a search box, grouping permissions by area (e.g., Posts, Users, Reports), and a \u201ccheck all in group\u201d toggle to minimize clicks.<\/p>\n\n\n\n<p><\/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>Wrapping Up<\/strong><\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>You now have a complete, user-friendly <strong>Roles &amp; Permissions UI<\/strong> in Laravel 12. Admins can create permissions, assign them directly to users, manage roles, and protect pages by role or permission. With consistent Bootstrap layouts and clear checkboxes, your admin team gets a fast, intuitive experience \u2014 and your app gets precise, maintainable access control.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-cover alignwide is-light\" style=\"min-height:100vh;aspect-ratio:unset;\"><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-100 has-background-dim\" style=\"background-color:#ffffff\"><\/span><div class=\"wp-block-cover__inner-container is-layout-constrained wp-block-cover-is-layout-constrained\">\n<h2 class=\"wp-block-heading\"><strong>Grab a production-ready implementation<\/strong><\/h2>\n\n\n\n<p class=\"is-style-default\">If you don\u2019t want to wire up all the edge cases (UI, roles, permissions, settings toggles, demos), <strong>Grab a production-ready implementation<\/strong>:<\/p>\n\n\n\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile is-vertically-aligned-center is-image-fill-element\" style=\"grid-template-columns:56% auto\"><figure class=\"wp-block-media-text__media\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"636\" src=\"https:\/\/1v0.net\/blog\/wp-content\/uploads\/2025\/08\/1-1024x636.jpg\" alt=\"\" class=\"wp-image-118 size-full\" style=\"object-position:50% 50%\" srcset=\"https:\/\/1v0.net\/blog\/wp-content\/uploads\/2025\/08\/1-1024x636.jpg 1024w, https:\/\/1v0.net\/blog\/wp-content\/uploads\/2025\/08\/1-300x186.jpg 300w, https:\/\/1v0.net\/blog\/wp-content\/uploads\/2025\/08\/1-768x477.jpg 768w, https:\/\/1v0.net\/blog\/wp-content\/uploads\/2025\/08\/1.jpg 1440w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><div class=\"wp-block-media-text__content\">\n<h2 class=\"wp-block-heading has-text-color\" style=\"color:#000000;font-size:32px\"><strong>Laravel Roles &amp; Permissions UI<\/strong><\/h2>\n\n\n\n<p class=\"has-text-color\" style=\"color:#000000;font-size:17px\">This lightweight Laravel starter kit helps you quickly integrate user roles and permissions using the popular spatie\/laravel-permission package.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button color--theme btn\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/1v0.net\/product\/laravel-roles-and-permissions-kit\">Learn more<\/a><\/div>\n<\/div>\n<\/div><\/div>\n<\/div><\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Roles make high-level access control simple, but sometimes you need finer control: specific users may need one or two extra abilities without changing their whole role. That\u2019s where a clean, admin-friendly Permissions UI helps. In this guide, you\u2019ll create a user-friendly interface in Laravel 12 to manage roles and permissions, assign both roles and individual [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":139,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[16,15,17],"class_list":["post-133","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","tag-permissions","tag-roles","tag-roles-and-permissions"],"_links":{"self":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/133","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=133"}],"version-history":[{"count":7,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/133\/revisions"}],"predecessor-version":[{"id":142,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/133\/revisions\/142"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media\/139"}],"wp:attachment":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media?parent=133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/categories?post=133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/tags?post=133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}