• Час читання ~9 хв
  • 10.09.2023

Існує купа пакетів для Laravel для управління ролями користувачів і дозволами. Спати, ролі та дозволи, а також ролі та дозволи Laratrust є найпопулярнішими з них. Ми можемо легко керувати ролями та дозволами в Laravel за допомогою цих пакетів. Але в цьому уроці наша мета — створити систему ролей і дозволів без будь-яких пакунків. Тому ми не збираємося використовувати будь-який тип пакета для створення цієї системи ролей і дозволів Laravel 10.

У цьому підручнику я створю повний Laravel 10 ролей і дозволів без пакета. Щоб створити ці ролі та системи дозволів Laravel, нам потрібно спочатку зрозуміти сценарій ролей та дозволів для користувача. Отже , що ми збираємося зробити в цьому підручнику, давайте подивимося сценарій:

  • Користувач може мати певну роль
  • Роль може мати багато дозволів
  • Користувачі можуть мати кілька ролей

Отже, це вимога, яку ми збираємося реалізувати. Ми також впроваджуємо проміжне програмне забезпечення та спеціальну директиву Blade для обробки зареєстрованих користувачів відповідно до їхніх ролей та дозволів.

laravel-custom-role-and-permission-inplementation

Давайте подивимося зображення інформаційної панелі попереднього перегляду цієї ролі та дозволів Laravel 10 tutorial:за допомогою такої команди:Крок 2: Крок 1: Завантажте Fresh Laravel На першому кроці Laravel 10 ролей та дозволів без пакета завантажте свіжу програму Laravel

laravel-10-roles-and-permissions-without-package

за допомогою такої команди:Крок 2: 

laravel-10-roles-and-permissions-tutorial

composer create-project laravel/laravel example-app

Створіть автентифікацію

Нам потрібна автентифікація. Щоб створити просту автентифікацію bootstrap за допомогою такої команди:Крок 3: Підключіть базу даних Тепер підключіть базу

composer require laravel/ui --dev
php artisan ui bootstrap --auth
npm install
npm run dev

даних, тому що нам потрібна міграція для цього Ролі та дозволи Laravel Приклад

:.env

Крок 4:

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

Зробіть модель Нам потрібна модель

, щоб зробити ролі та дозволи користувачів. Отже, давайте створимо нашу модель, використовуючи наведену нижче команду, щоб виконати 10 ролей і дозволів Laravel без пакета.

php artisan make:model Permission -m
php artisan make:model Role -m

Тепер оновіть файл міграції, наприклад:

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('roles');
    }
};

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('permissions', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('permissions');
    }
};

Тепер час створити кілька зведених таблиць, Ми створимо новий файл міграції для таблиці users_permissions. Отже, запустіть наведену нижче команду, щоб створити

<?php
use App\Models\Permission;
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users_permissions', function (Blueprint $table) {
            $table->foreignIdFor(User::class)->constrained()->cascadeOnDelete();
            $table->foreignIdFor(Permission::class)->constrained()->cascadeOnDelete();
        });
    }
    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('users_permissions');
    }
};

Тепер давайте створимо зведену таблицю для 

<?php
use App\Models\Role;
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users_roles', function (Blueprint $table) {
            $table->foreignIdFor(User::class)->constrained()->cascadeOnDelete();
            $table->foreignIdFor(Role::class)->constrained()->cascadeOnDelete();
        });
    }
    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('users_roles');
    }
};

users_rolesУ певній ролі користувач може мати певний дозвіл. Наприклад, користувач може мати дозвіл на публікацію теми, а адміністратор може мати дозвіл редагувати або видаляти тему. У цьому випадку давайте налаштуємо нову таблицю, щоб roles_permissions впоралися з цією складністю.

php artisan make:migration create_roles_permissions_table --create=roles_permissions

Тепер оновіть подібнеroles_permissions:Тепер запустіть таку команду, щоб створити міграцію

<?php
use App\Models\Permission;
use App\Models\Role;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('roles_permissions', function (Blueprint $table) {
            $table->foreignIdFor(Role::class)->constrained()->cascadeOnDelete();
            $table->foreignIdFor(Permission::class)->constrained()->cascadeOnDelete();
        });
    }
    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('roles_permissions');
    }
};

Крок5: Оновіть модель із зв'язкомТепер оновіть рольову модель за допомогою такого зв'язку:app\Models\Role.php Тепер оновіть модель дозволів за допомогою такого зв'язку

php artisan migrate

:

Крок 6: 

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
    use HasFactory;
    public function permissions()
    {
        return $this->belongsToMany(Permission::class, 'roles_permissions');
    }
    public function users()
    {
        return $this->belongsToMany(User::class, 'users_roles');
    }
}

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
    use HasFactory;
    public function roles()
    {
        return $this->belongsToMany(Role::class, 'roles_permissions');
    }
    public function users()
    {
        return $this->belongsToMany(User::class, 'users_permissions');
    }
}

Створіть рису служби

Тепер на цьому кроці ми створимо службу або допоміжну рису для легкої обробки ролей та дозволів у програмі Laravel 10.

App\Traits\HasPermissionsTrait.php

<?php
namespace App\Traits;
use App\Models\Role;
use App\Models\Permission;
trait HasPermissionsTrait
{
    public function givePermissionsTo(...$permissions)
    {
        $permissions = $this->getAllPermissions($permissions);
        if ($permissions === null) {
            return $this;
        }
        $this->permissions()->saveMany($permissions);
        return $this;
    }
    public function withdrawPermissionsTo(...$permissions)
    {
        $permissions = $this->getAllPermissions($permissions);
        $this->permissions()->detach($permissions);
        return $this;
    }
    public function refreshPermissions(...$permissions)
    {
        $this->permissions()->detach();
        return $this->givePermissionsTo($permissions);
    }
    public function hasPermissionTo($permission)
    {
        return $this->hasPermissionThroughRole($permission) || $this->hasPermission($permission);
    }
    public function hasPermissionThroughRole($permission)
    {
        foreach($permission->roles as $role) {
            if ($this->roles->contains($role)) {
                return true;
            }
        }
        return false;
    }
    public function hasRole(...$roles)
    {
        foreach($roles as $role) {
            if ($this->roles->contains('name', $role)) {
                return true;
            }
        }
        return false;
    }
    public function roles()
    {
        return $this->belongsToMany(Role::class, 'users_roles');
    }
    public function permissions()
    {
        return $this->belongsToMany(Permission::class, 'users_permissions');
    }
    protected function hasPermission($permission)
    {
        return (bool) $this->permissions->where('name', $permission->name)->count();
    }
    protected function getAllPermissions(array $permissions)
    {
        return Permission::whereIn('name', $permissions)->get();
    }
}

Тепер оновіть модель користувача, використовуючи цю рису.

app\Models\Користувач.php

<?php
namespace App\Models;
use App\Traits\HasPermissionsTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
    use HasApiTokens,
        HasFactory,
        Notifiable,
        HasPermissionsTrait;
    protected $fillable = [
        'name',
        'email',
        'password',
    ];
    protected $hidden = [
        'password',
        'remember_token',
    ];
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];
}

Крок 7: Створіть директиву

про рольовий клинокТепер цього разу ми створимо директиву @role() про лезо. Тож оновіть постачальника послуг додатків, наприклад:App\Providers\AppServiceProvider.php

Крок 8:

<?php
namespace App\Providers;
use App\Models\Permission;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
    }
    public function boot(): void
    {
        try {
            Permission::get()->map(function ($permission) {
                Gate::define($permission->name, function ($user) use ($permission) {
                    return $user->hasPermissionTo($permission);
                });
            });
        } catch (\Exception $e) {
            report($e);
        }
        Blade::directive('role', function ($role) {
            return "<?php if(auth()->check() && auth()->user()->hasRole({$role})) : ?>";
        });
        Blade::directive('endrole', function ($role) {
            return "<?php endif; ?>";
        });
    }
}

Створіть сівалку

Тепер на цьому кроці ми створимо деякі фіктивні дані для створення ролей і дозволів з користувачами. Отже, запустіть наведену нижче команду:Тепер оновіть її так:База даних\Seeders\RoleSeeder.php Тепер оновіть сівалку бази даних так:

php artisan make:seeder RoleSeeder

<?php
namespace Database\Seeders;
use App\Models\Role;
use App\Models\User;
use App\Models\Permission;
use Illuminate\Database\Seeder;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
class RoleSeeder extends Seeder
{
    public function run(): void
    {
        $permission = new Permission();
        $permission->name = 'create-post';
        $permission->save();
        $role = new Role();
        $role->name = 'admin';
        $role->save();
        $role->permissions()->attach($permission);
        $permission->roles()->attach($role);
        $permission = new Permission();
        $permission->name = 'create-user';
        $permission->save();
        $role = new Role();
        $role->name = 'user';
        $role->save();
        $role->permissions()->attach($permission);
        $permission->roles()->attach($role);
        $admin = Role::where('name', 'admin')->first();
        $userRole = Role::where('name', 'user')->first();
        $create_post = Permission::where('name', 'create-post')->first();
        $create_user = Permission::where('name', 'create-user')->first();
        $admin = new User();
        $admin->name = 'Admin';
        $admin->email = '[email protected]';
        $admin->password = bcrypt('admin');
        $admin->save();
        $admin->roles()->attach($admin);
        $admin->permissions()->attach($create_post);
        $user = new User();
        $user->name = 'User';
        $user->email = '[email protected]';
        $user->password = bcrypt('user');
        $user->save();
        $user->roles()->attach($userRole);
        $user->permissions()->attach($create_user);
    }
}

DatabaseSeeder\DatabaseSeeder.php

Тепер запустіть наведену нижче команду,

<?php
namespace Database\Seeders;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $this->call(RoleSeeder::class);
    }
}

щоб створити деякі підроблені дані, щоб перевірити наші ролі та дозволи laravel 10 без застосування пакета.

php artisan db:seed

Крок 9: Створіть проміжне програмне забезпечення

На цьому кроці ми створимо рольове проміжне програмне забезпечення, щоб ми могли обробляти запити користувачів за допомогою проміжного програмного забезпечення.

php artisan make:middleware RoleMiddleware

І оновіть його так:App\Http\Middleware\RoleMiddleware.php Тепер зареєструйте його всередині kernel.php такого:

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class RoleMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(
        Request $request,
        Closure $next,
        $role,
        $permission = null
    ): Response {
        if (!$request->user()->hasRole($role)) {
            abort(404);
        }
        if ($permission !== null && !$request->user()->can($permission)) {
            abort(404);
        }
        return $next($request);
    }
}

<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array<int, class-string|string>
     */
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];
    /**
     * The application's route middleware groups.
     *
     * @var array<string, array<int, class-string|string>>
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];
    /**
     * The application's middleware aliases.
     *
     * Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
     *
     * @var array<string, class-string|string>
     */
    protected $middlewareAliases = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
        'signed' => \App\Http\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        'role' => \App\Http\Middleware\RoleMiddleware::class,
    ];
}

Тепер все готово. Ми можемо перевіряти запити користувачів та ролі так:

resources/views/home.blade.php

@extends('layouts.app')
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>
                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    @role('admin')
                        {{ __('You are admin') }}
                    @endrole
                    @role('user')
                        {{ __('You are user') }}
                    @endrole
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Перевірте ролі користувачів та дозволи в контролері:Використовуйте у своєму маршруті так:маршрути/Інтернет.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TutorialController extends Controller
{
    public function __invoke()
    {
        if (auth()->user()->can('create-user')) {
            return view('welcome');
        }
    }
}

Використання в груповому маршруті:Читайте також: 

<?php
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TutorialController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/
Route::get('/', TutorialController::class)->middleware('role:admin');

Route::group(['middleware' => 'role:admin'], function() {
   //
});
Route::group(['middleware' => 'role:user'], function() {
   //
});

Laravel 10 Twilio Надіслати SMS Підручник

висновок

Подивіться на це, ми впровадили всі вимоги, пов'язані з ролями та дозволами. Сподіваюся, тепер у будь-яких програмах Laravel ми можемо реалізувати ці 10 ролей та дозволів без пакета. Сподіваюся, цей підручник з ролей та дозволів допоможе вам.

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297