Originally posted @ https://codeanddeploy.com Посетите и скачайте пример кода: https://codeanddeploy.com/blog/laravel/laravel-8-user-roles-and-permissions-step-by-step-tutorial
В этом посте я расскажу, как реализовать ACL-метод Roles & Permissions на Laravel 8 с помощью пошагового руководства, которое поможет вам понять процесс. Мы знаем, что реализация ролей и разрешений пользователей является одной из основных функций, которые необходимо реализовать в наших веб-приложениях, чтобы ограничить доступ конкретного пользователя, разрешив его только администратору. Вот почему нам необходимо реализовать пользователей на основе ролей с назначенными разрешениями. В этом примере я автоматически считываю маршрут как разрешение через промежуточное ПО, так что вам не нужно добавлять его вручную. В этом примере также есть возможность добавить разрешение вручную.
Следуя этому руководству, будет проще реализовать разрешения Laravel и защитить учетные записи пользователей.
В этом примере я добавил следующие модули:
- Управление пользователями
- Создание простого управления пользователями с помощью Laravel 8, чтобы вам было проще применять разрешения Laravel.
- Управление ролями
- Простое управление ролями, которое поможет нам добавить роли для учетной записи пользователя и определить, какому пользователю назначено разрешение Laravel.
- Управление разрешениями
- Управление разрешениями Laravel, которое позволит перечислить все имена маршрутов с помощью команды консоли Laravel.
- Управление продуктами
- Простое управление продуктом и применение для Laravel разрешений с каждой ролью в качестве пользователя.
С аутентификацией, которую вы можете пройти в моем предыдущем руководстве.
Итак, давайте начнем…
Шаг 1: Установка Laravel
Я предполагаю, что ваш проект уже находится у вас в локальной сети. Чтобы сократить этот пост, пожалуйста, следуйте моему предыдущему руководству с функцией аутентификации.
Или запустите и клонируйте мой предыдущий учебник по аутентификации.
git clone https://github.com/codeanddeploy/laravel8-authentication-example.git
Затем, после клонирования, просто скопируйте и вставьте его в htdocs, если вы используете Wampp на Windows.
Затем перейдите в свой проект и выполните эту команду:
composer update
Шаг 2: Установка пакетов
Далее нам нужно установить пакеты Laravel для ACL и Form Collections. Выполните следующую команду:
composer require spatie/laravel-permission
composer require laravelcollective/html
Затем выполните следующую команду:
php artisan vendor:publish --provider="SpatiePermissionPermissionServiceProvider"
После выполнения вышеуказанной команды вы увидите файл конфигурации с именем permission.php
и миграции с **_permission_tables.php*. Теперь давайте выполним команду для миграции таблиц разрешений.
php artisan migrate
Шаг 3: Создание миграции постов
Далее мы создадим миграцию для таблицы постов. Для этого выполните следующую команду.
php artisan make:migration create_posts_table
Затем выполним пост-миграцию. Полный код приведен ниже:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('title', 70);
$table->string('description', 320);
$table->text('body');
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
Затем запустите миграцию:
php artisan migrate
Шаг 4: Создание моделей
Далее мы создадим наши модели и настроим важные детали. Если вы используете мой предыдущий учебник по аутентификации, вам просто нужно обновить модель User. Смотрите следующие полные коды ниже:
app/Models/User.php
<?php
namespace AppModels;
use LaravelSanctumHasApiTokens;
use SpatiePermissionTraitsHasRoles;
use IlluminateNotificationsNotifiable;
use IlluminateContractsAuthMustVerifyEmail;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateFoundationAuthUser as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable, HasRoles;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'username',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* Always encrypt password when it is updated.
*
* @param $value
* @return string
*/
public function setPasswordAttribute($value)
{
$this->attributes['password'] = bcrypt($value);
}
}
Далее мы сгенерируем модель для Post. Выполните следующую команду:
php artisan make:model Post
Код модели Post приведен ниже:
app/Models/Post.php
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Post extends Model
{
use HasFactory;
protected $table = 'posts';
protected $fillable = [
'user_id',
'title',
'description',
'body'
];
}
Шаг 5: Добавьте промежуточное ПО
В этом примере я делаю пользовательское промежуточное ПО для нашего разрешения, чтобы прочитать текущий маршрут, если он существует для нашего разрешения.
Давайте создадим наше пользовательское промежуточное ПО. Выполните следующую команду:
php artisan make:middleware PermissionMiddleware
А вот пользовательский код нашего класса PermissionMiddlware. Перейдите в AppHttpMiddlewarePermissionMiddleware.php
<?php
namespace AppHttpMiddleware;
use Closure;
use IlluminateHttpRequest;
use SpatiePermissionExceptionsUnauthorizedException;
class PermissionMiddleware
{
/**
* Handle an incoming request.
*
* @param IlluminateHttpRequest $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next, $permission = null, $guard = null)
{
$authGuard = app('auth')->guard($guard);
if ($authGuard->guest()) {
throw UnauthorizedException::notLoggedIn();
}
if (! is_null($permission)) {
$permissions = is_array($permission)
? $permission
: explode('|', $permission);
}
if ( is_null($permission) ) {
$permission = $request->route()->getName();
$permissions = array($permission);
}
foreach ($permissions as $permission) {
if ($authGuard->user()->can($permission)) {
return $next($request);
}
}
throw UnauthorizedException::forPermissions($permissions);
}
}
Затем давайте зарегистрируем созданное нами промежуточное ПО и промежуточное ПО Spatie по умолчанию.
Теперь перейдем в файл app/Http/Kernel.php и в свойстве $routeMiddleware добавим следующие промежуточные модули.
protected $routeMiddleware = [
.
.
.
'role' => SpatiePermissionMiddlewaresRoleMiddleware::class,
'permission' => AppHttpMiddlewarePermissionMiddleware::class,
'role_or_permission' => SpatiePermissionMiddlewaresRoleOrPermissionMiddleware::class,
];
Как вы можете видеть выше, мы добавили наше пользовательское промежуточное ПО.
Шаг 6: Добавление маршрутов
Теперь давайте добавим наши маршруты, если вы используете мою аутентификацию Laravel 8, просто отредактируйте или скопируйте полные коды маршрутов ниже:
<?php
use IlluminateSupportFacadesRoute;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::group(['namespace' => 'AppHttpControllers'], function()
{
/**
* Home Routes
*/
Route::get('/', 'HomeController@index')->name('home.index');
Route::group(['middleware' => ['guest']], function() {
/**
* Register Routes
*/
Route::get('/register', 'RegisterController@show')->name('register.show');
Route::post('/register', 'RegisterController@register')->name('register.perform');
/**
* Login Routes
*/
Route::get('/login', 'LoginController@show')->name('login.show');
Route::post('/login', 'LoginController@login')->name('login.perform');
});
Route::group(['middleware' => ['auth', 'permission']], function() {
/**
* Logout Routes
*/
Route::get('/logout', 'LogoutController@perform')->name('logout.perform');
/**
* User Routes
*/
Route::group(['prefix' => 'users'], function() {
Route::get('/', 'UsersController@index')->name('users.index');
Route::get('/create', 'UsersController@create')->name('users.create');
Route::post('/create', 'UsersController@store')->name('users.store');
Route::get('/{user}/show', 'UsersController@show')->name('users.show');
Route::get('/{user}/edit', 'UsersController@edit')->name('users.edit');
Route::patch('/{user}/update', 'UsersController@update')->name('users.update');
Route::delete('/{user}/delete', 'UsersController@destroy')->name('users.destroy');
});
/**
* User Routes
*/
Route::group(['prefix' => 'posts'], function() {
Route::get('/', 'PostsController@index')->name('posts.index');
Route::get('/create', 'PostsController@create')->name('posts.create');
Route::post('/create', 'PostsController@store')->name('posts.store');
Route::get('/{post}/show', 'PostsController@show')->name('posts.show');
Route::get('/{post}/edit', 'PostsController@edit')->name('posts.edit');
Route::patch('/{post}/update', 'PostsController@update')->name('posts.update');
Route::delete('/{post}/delete', 'PostsController@destroy')->name('posts.destroy');
});
Route::resource('roles', RolesController::class);
Route::resource('permissions', PermissionsController::class);
});
});
Шаг 7: Добавить контроллеры
В этом шаге мы добавим контроллеры для пользователей, постов, ролей и разрешений, как показано ниже:
AppHttpControllersUsersController.php
<?php
namespace AppHttpControllers;
use AppModelsUser;
use IlluminateHttpRequest;
use SpatiePermissionModelsRole;
use AppHttpRequestsStoreUserRequest;
use AppHttpRequestsUpdateUserRequest;
class UsersController extends Controller
{
/**
* Display all users
*
* @return IlluminateHttpResponse
*/
public function index()
{
$users = User::latest()->paginate(10);
return view('users.index', compact('users'));
}
/**
* Show form for creating user
*
* @return IlluminateHttpResponse
*/
public function create()
{
return view('users.create');
}
/**
* Store a newly created user
*
* @param User $user
* @param StoreUserRequest $request
*
* @return IlluminateHttpResponse
*/
public function store(User $user, StoreUserRequest $request)
{
//For demo purposes only. When creating user or inviting a user
// you should create a generated random password and email it to the user
$user->create(array_merge($request->validated(), [
'password' => 'test'
]));
return redirect()->route('users.index')
->withSuccess(__('User created successfully.'));
}
/**
* Show user data
*
* @param User $user
*
* @return IlluminateHttpResponse
*/
public function show(User $user)
{
return view('users.show', [
'user' => $user
]);
}
/**
* Edit user data
*
* @param User $user
*
* @return IlluminateHttpResponse
*/
public function edit(User $user)
{
return view('users.edit', [
'user' => $user,
'userRole' => $user->roles->pluck('name')->toArray(),
'roles' => Role::latest()->get()
]);
}
/**
* Update user data
*
* @param User $user
* @param UpdateUserRequest $request
*
* @return IlluminateHttpResponse
*/
public function update(User $user, UpdateUserRequest $request)
{
$user->update($request->validated());
$user->syncRoles($request->get('role'));
return redirect()->route('users.index')
->withSuccess(__('User updated successfully.'));
}
/**
* Delete user data
*
* @param User $user
*
* @return IlluminateHttpResponse
*/
public function destroy(User $user)
{
$user->delete();
return redirect()->route('users.index')
->withSuccess(__('User deleted successfully.'));
}
}
AppHttpControllersPostsController.php
<?php
namespace AppHttpControllers;
use AppModelsPost;
use IlluminateHttpRequest;
class PostsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return IlluminateHttpResponse
*/
public function index()
{
$posts = Post::latest()->paginate(10);
return view('posts.index', compact('posts'));
}
/**
* Show the form for creating a new resource.
*
* @return IlluminateHttpResponse
*/
public function create()
{
return view('posts.create');
}
/**
* Store a newly created resource in storage.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
public function store(Request $request)
{
Post::create(array_merge($request->only('title', 'description', 'body'),[
'user_id' => auth()->id()
]));
return redirect()->route('posts.index')
->withSuccess(__('Post created successfully.'));
}
/**
* Display the specified resource.
*
* @param AppModelsPost $post
* @return IlluminateHttpResponse
*/
public function show(Post $post)
{
return view('posts.show', [
'post' => $post
]);
}
/**
* Show the form for editing the specified resource.
*
* @param AppModelsPost $post
* @return IlluminateHttpResponse
*/
public function edit(Post $post)
{
return view('posts.edit', [
'post' => $post
]);
}
/**
* Update the specified resource in storage.
*
* @param IlluminateHttpRequest $request
* @param AppModelsPost $post
* @return IlluminateHttpResponse
*/
public function update(Request $request, Post $post)
{
$post->update($request->only('title', 'description', 'body'));
return redirect()->route('posts.index')
->withSuccess(__('Post updated successfully.'));
}
/**
* Remove the specified resource from storage.
*
* @param AppModelsPost $post
* @return IlluminateHttpResponse
*/
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')
->withSuccess(__('Post deleted successfully.'));
}
}
AppHttpControllersRolesController.php
<?php
namespace AppHttpControllers;
use DB;
use IlluminateHttpRequest;
use SpatiePermissionModelsRole;
use AppHttpControllersController;
use IlluminateSupportFacadesRoute;
use SpatiePermissionModelsPermission;
class RolesController extends Controller
{
/**
* Display a listing of the resource.
*
* @return IlluminateHttpResponse
*/
function __construct()
{
}
/**
* Display a listing of the resource.
*
* @return IlluminateHttpResponse
*/
public function index(Request $request)
{
$roles = Role::orderBy('id','DESC')->paginate(5);
return view('roles.index',compact('roles'))
->with('i', ($request->input('page', 1) - 1) * 5);
}
/**
* Show the form for creating a new resource.
*
* @return IlluminateHttpResponse
*/
public function create()
{
$permissions = Permission::get();
return view('roles.create', compact('permissions'));
}
/**
* Store a newly created resource in storage.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|unique:roles,name',
'permission' => 'required',
]);
$role = Role::create(['name' => $request->get('name')]);
$role->syncPermissions($request->get('permission'));
return redirect()->route('roles.index')
->with('success','Role created successfully');
}
/**
* Display the specified resource.
*
* @param int $id
* @return IlluminateHttpResponse
*/
public function show(Role $role)
{
$role = $role;
$rolePermissions = $role->permissions;
return view('roles.show', compact('role', 'rolePermissions'));
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return IlluminateHttpResponse
*/
public function edit(Role $role)
{
$role = $role;
$rolePermissions = $role->permissions->pluck('name')->toArray();
$permissions = Permission::get();
return view('roles.edit', compact('role', 'rolePermissions', 'permissions'));
}
/**
* Update the specified resource in storage.
*
* @param IlluminateHttpRequest $request
* @param int $id
* @return IlluminateHttpResponse
*/
public function update(Role $role, Request $request)
{
$this->validate($request, [
'name' => 'required',
'permission' => 'required',
]);
$role->update($request->only('name'));
$role->syncPermissions($request->get('permission'));
return redirect()->route('roles.index')
->with('success','Role updated successfully');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return IlluminateHttpResponse
*/
public function destroy(Role $role)
{
$role->delete();
return redirect()->route('roles.index')
->with('success','Role deleted successfully');
}
}
AppHttpControllersPermissionsController.php
<?php
namespace AppHttpControllers;
use IlluminateHttpRequest;
use IlluminateSupportFacadesRoute;
use SpatiePermissionModelsPermission;
class PermissionsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return IlluminateHttpResponse
*/
public function index()
{
$permissions = Permission::all();
return view('permissions.index', [
'permissions' => $permissions
]);
}
/**
* Show form for creating permissions
*
* @return IlluminateHttpResponse
*/
public function create()
{
return view('permissions.create');
}
/**
* Store a newly created resource in storage.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
public function store(Request $request)
{
$request->validate([
'name' => 'required|unique:users,name'
]);
Permission::create($request->only('name'));
return redirect()->route('permissions.index')
->withSuccess(__('Permission created successfully.'));
}
/**
* Show the form for editing the specified resource.
*
* @param Permission $post
* @return IlluminateHttpResponse
*/
public function edit(Permission $permission)
{
return view('permissions.edit', [
'permission' => $permission
]);
}
/**
* Update the specified resource in storage.
*
* @param IlluminateHttpRequest $request
* @param Permission $permission
* @return IlluminateHttpResponse
*/
public function update(Request $request, Permission $permission)
{
$request->validate([
'name' => 'required|unique:permissions,name,'.$permission->id
]);
$permission->update($request->only('name'));
return redirect()->route('permissions.index')
->withSuccess(__('Permission updated successfully.'));
}
/**
* Remove the specified resource from storage.
*
* @param AppModelsPost $post
* @return IlluminateHttpResponse
*/
public function destroy(Permission $permission)
{
$permission->delete();
return redirect()->route('permissions.index')
->withSuccess(__('Permission deleted successfully.'));
}
}
Шаг 8: Добавление запросов
В моем UsersController я реализовал конкретный запрос для каждого действия, это поможет сократить ваш код и поместить другие функции и проверки в другой класс, и ваш код будет более читабельным.
Выполните следующие команды для создания запросов:
php artisan make:request StoreUserRequest
php artisan make:request UpdateUserRequest
После этого, пожалуйста, посмотрите код каждого запроса.
AppHttpRequestsStoreUserRequest.php
<?php
namespace AppHttpRequests;
use IlluminateFoundationHttpFormRequest;
class StoreUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required',
'email' => 'required|email:rfc,dns|unique:users,email',
'username' => 'required|unique:users,username',
];
}
}
AppHttpRequestsUpdateUserRequest.php
<?php
namespace AppHttpRequests;
use IlluminateFoundationHttpFormRequest;
class UpdateUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
// Let's get the route param by name to get the User object value
$user = request()->route('user');
return [
'name' => 'required',
'email' => 'required|email:rfc,dns|unique:users,email,'.$user->id,
'username' => 'required|unique:users,username,'.$user->id,
];
}
}
Шаг 9: Добавление файлов лезвий
В этом посте мы создадим файлы блейдов для нашего представления и макета.
resources/views/layouts/app-master.blade.php
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
<meta name="generator" content="Hugo 0.87.0">
<title>Fixed top navbar example · Bootstrap v5.1</title>
<!-- Bootstrap core CSS -->
<link href="{!! url('assets/bootstrap/css/bootstrap.min.css') !!}" rel="stylesheet">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
.float-right {
float: right;
}
</style>
<!-- Custom styles for this template -->
<link href="{!! url('assets/css/app.css') !!}" rel="stylesheet">
</head>
<body>
@include('layouts.partials.navbar')
<main class="container mt-5">
@yield('content')
</main>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="{!! url('assets/bootstrap/js/bootstrap.bundle.min.js') !!}"></script>
@section("scripts")
@show
</body>
</html>
resources/views/layouts/partials/messages.blade.php
resources/views/layouts/partials/messages.blade.php
@if(Session::get('success', false))
<?php $data = Session::get('success'); ?>
@if (is_array($data))
@foreach ($data as $msg)
<div class="alert alert-success" role="alert">
<i class="fa fa-check"></i>
{{ $msg }}
</div>
@endforeach
@else
<div class="alert alert-success" role="alert">
<i class="fa fa-check"></i>
{{ $data }}
</div>
@endif
@endif
resources/views/layouts/partials/navbar.blade.php
<header class="p-3 bg-dark text-white">
<div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
<svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap"><use xlink:href="#bootstrap"/></svg>
</a>
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
<li><a href="{{ route('home.index') }}" class="nav-link px-2 text-white">Home</a></li>
@auth
@role('Admin')
<li><a href="{{ route('users.index') }}" class="nav-link px-2 text-white">Users</a></li>
<li><a href="{{ route('roles.index') }}" class="nav-link px-2 text-white">Roles</a></li>
@endrole
<li><a href="{{ route('posts.index') }}" class="nav-link px-2 text-white">Posts</a></li>
@endauth
</ul>
<form class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3">
<input type="search" class="form-control form-control-dark" placeholder="Search..." aria-label="Search">
</form>
@auth
{{auth()->user()->name}}
<div class="text-end">
<a href="{{ route('logout.perform') }}" class="btn btn-outline-light me-2">Logout</a>
</div>
@endauth
@guest
<div class="text-end">
<a href="{{ route('login.perform') }}" class="btn btn-outline-light me-2">Login</a>
<a href="{{ route('register.perform') }}" class="btn btn-warning">Sign-up</a>
</div>
@endguest
</div>
</div>
</header>
resources/views/permissions/create.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h2>Add new permission</h2>
<div class="lead">
Add new permission.
</div>
<div class="container mt-4">
<form method="POST" action="{{ route('permissions.store') }}">
@csrf
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input value="{{ old('name') }}"
type="text"
class="form-control"
name="name"
placeholder="Name" required>
@if ($errors->has('name'))
<span class="text-danger text-left">{{ $errors->first('name') }}</span>
@endif
</div>
<button type="submit" class="btn btn-primary">Save permission</button>
<a href="{{ route('permissions.index') }}" class="btn btn-default">Back</a>
</form>
</div>
</div>
@endsection
resources/views/permissions/edit.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h2>Edit permission</h2>
<div class="lead">
Editing permission.
</div>
<div class="container mt-4">
<form method="POST" action="{{ route('permissions.update', $permission->id) }}">
@method('patch')
@csrf
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input value="{{ $permission->name }}"
type="text"
class="form-control"
name="name"
placeholder="Name" required>
@if ($errors->has('name'))
<span class="text-danger text-left">{{ $errors->first('name') }}</span>
@endif
</div>
<button type="submit" class="btn btn-primary">Save permission</button>
<a href="{{ route('permissions.index') }}" class="btn btn-default">Back</a>
</form>
</div>
</div>
@endsection
ресурсы/views/permissions/index.blade.php
@extends('layouts.app-master')
@section('content')
<h1 class="mb-3">Laravel 8 User Roles and Permissions Step by Step Tutorial - codeanddeploy.com</h1>
<div class="bg-light p-4 rounded">
<h2>Permissions</h2>
<div class="lead">
Manage your permissions here.
<a href="{{ route('permissions.create') }}" class="btn btn-primary btn-sm float-right">Add permissions</a>
</div>
<div class="mt-2">
@include('layouts.partials.messages')
</div>
<table class="table table-striped">
<thead>
<tr>
<th scope="col" width="15%">Name</th>
<th scope="col">Guard</th>
<th scope="col" colspan="3" width="1%"></th>
</tr>
</thead>
<tbody>
@foreach($permissions as $permission)
<tr>
<td>{{ $permission->name }}</td>
<td>{{ $permission->guard_name }}</td>
<td><a href="{{ route('permissions.edit', $permission->id) }}" class="btn btn-info btn-sm">Edit</a></td>
<td>
{!! Form::open(['method' => 'DELETE','route' => ['permissions.destroy', $permission->id],'style'=>'display:inline']) !!}
{!! Form::submit('Delete', ['class' => 'btn btn-danger btn-sm']) !!}
{!! Form::close() !!}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endsection
resources/views/posts/create.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h2>Add new post</h2>
<div class="lead">
Add new post.
</div>
<div class="container mt-4">
<form method="POST" action="{{ route('posts.store') }}">
@csrf
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input value="{{ old('title') }}"
type="text"
class="form-control"
name="title"
placeholder="Title" required>
@if ($errors->has('title'))
<span class="text-danger text-left">{{ $errors->first('title') }}</span>
@endif
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<input value="{{ old('description') }}"
type="text"
class="form-control"
name="description"
placeholder="Description" required>
@if ($errors->has('description'))
<span class="text-danger text-left">{{ $errors->first('description') }}</span>
@endif
</div>
<div class="mb-3">
<label for="body" class="form-label">Body</label>
<textarea class="form-control"
name="body"
placeholder="Body" required>{{ old('body') }}</textarea>
@if ($errors->has('body'))
<span class="text-danger text-left">{{ $errors->first('body') }}</span>
@endif
</div>
<button type="submit" class="btn btn-primary">Save role</button>
<a href="{{ route('posts.index') }}" class="btn btn-default">Back</a>
</form>
</div>
</div>
@endsection
resources/views/posts/edit.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h2>Update post</h2>
<div class="lead">
Edit post.
</div>
<div class="container mt-4">
<form method="POST" action="{{ route('posts.update', $post->id) }}">
@method('patch')
@csrf
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input value="{{ $post->title }}"
type="text"
class="form-control"
name="title"
placeholder="Title" required>
@if ($errors->has('title'))
<span class="text-danger text-left">{{ $errors->first('title') }}</span>
@endif
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<input value="{{ $post->description }}"
type="text"
class="form-control"
name="description"
placeholder="Description" required>
@if ($errors->has('description'))
<span class="text-danger text-left">{{ $errors->first('description') }}</span>
@endif
</div>
<div class="mb-3">
<label for="body" class="form-label">Body</label>
<textarea
type="text"
class="form-control"
name="body"
placeholder="Body" required>{{ $post->body }}</textarea>
@if ($errors->has('body'))
<span class="text-danger text-left">{{ $errors->first('body') }}</span>
@endif
</div>
<button type="submit" class="btn btn-primary">Save changes</button>
<a href="{{ route('posts.index') }}" class="btn btn-default">Back</a>
</form>
</div>
</div>
@endsection
ресурсы/views/posts/index.blade.php
@extends('layouts.app-master')
@section('content')
<h1 class="mb-3">Laravel 8 User Roles and Permissions Step by Step Tutorial - codeanddeploy.com</h1>
<div class="bg-light p-4 rounded">
<h2>Posts</h2>
<div class="lead">
Manage your posts here.
<a href="{{ route('posts.create') }}" class="btn btn-primary btn-sm float-right">Add post</a>
</div>
<div class="mt-2">
@include('layouts.partials.messages')
</div>
<table class="table table-bordered">
<tr>
<th width="1%">No</th>
<th>Name</th>
<th width="3%" colspan="3">Action</th>
</tr>
@foreach ($posts as $key => $post)
<tr>
<td>{{ $post->id }}</td>
<td>{{ $post->title }}</td>
<td>
<a class="btn btn-info btn-sm" href="{{ route('posts.show', $post->id) }}">Show</a>
</td>
<td>
<a class="btn btn-primary btn-sm" href="{{ route('posts.edit', $post->id) }}">Edit</a>
</td>
<td>
{!! Form::open(['method' => 'DELETE','route' => ['posts.destroy', $post->id],'style'=>'display:inline']) !!}
{!! Form::submit('Delete', ['class' => 'btn btn-danger btn-sm']) !!}
{!! Form::close() !!}
</td>
</tr>
@endforeach
</table>
<div class="d-flex">
{!! $posts->links() !!}
</div>
</div>
@endsection
ресурсы/views/posts/show.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h2>Show post</h2>
<div class="lead">
</div>
<div class="container mt-4">
<div>
Title: {{ $post->title }}
</div>
<div>
Description: {{ $post->description }}
</div>
<div>
Body: {{ $post->body }}
</div>
</div>
</div>
<div class="mt-4">
<a href="{{ route('posts.edit', $post->id) }}" class="btn btn-info">Edit</a>
<a href="{{ route('posts.index') }}" class="btn btn-default">Back</a>
</div>
@endsection
ресурсы/views/роли/создать.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h1>Add new role</h1>
<div class="lead">
Add new role and assign permissions.
</div>
<div class="container mt-4">
@if (count($errors) > 0)
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('roles.store') }}">
@csrf
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input value="{{ old('name') }}"
type="text"
class="form-control"
name="name"
placeholder="Name" required>
</div>
<label for="permissions" class="form-label">Assign Permissions</label>
<table class="table table-striped">
<thead>
<th scope="col" width="1%"><input type="checkbox" name="all_permission"></th>
<th scope="col" width="20%">Name</th>
<th scope="col" width="1%">Guard</th>
</thead>
@foreach($permissions as $permission)
<tr>
<td>
<input type="checkbox"
name="permission[{{ $permission->name }}]"
value="{{ $permission->name }}"
class='permission'>
</td>
<td>{{ $permission->name }}</td>
<td>{{ $permission->guard_name }}</td>
</tr>
@endforeach
</table>
<button type="submit" class="btn btn-primary">Save user</button>
<a href="{{ route('users.index') }}" class="btn btn-default">Back</a>
</form>
</div>
</div>
@endsection
@section('scripts')
<script type="text/javascript">
$(document).ready(function() {
$('[name="all_permission"]').on('click', function() {
if($(this).is(':checked')) {
$.each($('.permission'), function() {
$(this).prop('checked',true);
});
} else {
$.each($('.permission'), function() {
$(this).prop('checked',false);
});
}
});
});
</script>
@endsection
resources/views/roles/edit.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h1>Update role</h1>
<div class="lead">
Edit role and manage permissions.
</div>
<div class="container mt-4">
@if (count($errors) > 0)
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('roles.update', $role->id) }}">
@method('patch')
@csrf
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input value="{{ $role->name }}"
type="text"
class="form-control"
name="name"
placeholder="Name" required>
</div>
<label for="permissions" class="form-label">Assign Permissions</label>
<table class="table table-striped">
<thead>
<th scope="col" width="1%"><input type="checkbox" name="all_permission"></th>
<th scope="col" width="20%">Name</th>
<th scope="col" width="1%">Guard</th>
</thead>
@foreach($permissions as $permission)
<tr>
<td>
<input type="checkbox"
name="permission[{{ $permission->name }}]"
value="{{ $permission->name }}"
class='permission'
{{ in_array($permission->name, $rolePermissions)
? 'checked'
: '' }}>
</td>
<td>{{ $permission->name }}</td>
<td>{{ $permission->guard_name }}</td>
</tr>
@endforeach
</table>
<button type="submit" class="btn btn-primary">Save changes</button>
<a href="{{ route('roles.index') }}" class="btn btn-default">Back</a>
</form>
</div>
</div>
@endsection
@section('scripts')
<script type="text/javascript">
$(document).ready(function() {
$('[name="all_permission"]').on('click', function() {
if($(this).is(':checked')) {
$.each($('.permission'), function() {
$(this).prop('checked',true);
});
} else {
$.each($('.permission'), function() {
$(this).prop('checked',false);
});
}
});
});
</script>
@endsection
resources/views/roles/index.blade.php
@extends('layouts.app-master')
@section('content')
<h1 class="mb-3">Laravel 8 User Roles and Permissions Step by Step Tutorial - codeanddeploy.com</h1>
<div class="bg-light p-4 rounded">
<h1>Roles</h1>
<div class="lead">
Manage your roles here.
<a href="{{ route('roles.create') }}" class="btn btn-primary btn-sm float-right">Add role</a>
</div>
<div class="mt-2">
@include('layouts.partials.messages')
</div>
<table class="table table-bordered">
<tr>
<th width="1%">No</th>
<th>Name</th>
<th width="3%" colspan="3">Action</th>
</tr>
@foreach ($roles as $key => $role)
<tr>
<td>{{ $role->id }}</td>
<td>{{ $role->name }}</td>
<td>
<a class="btn btn-info btn-sm" href="{{ route('roles.show', $role->id) }}">Show</a>
</td>
<td>
<a class="btn btn-primary btn-sm" href="{{ route('roles.edit', $role->id) }}">Edit</a>
</td>
<td>
{!! Form::open(['method' => 'DELETE','route' => ['roles.destroy', $role->id],'style'=>'display:inline']) !!}
{!! Form::submit('Delete', ['class' => 'btn btn-danger btn-sm']) !!}
{!! Form::close() !!}
</td>
</tr>
@endforeach
</table>
<div class="d-flex">
{!! $roles->links() !!}
</div>
</div>
@endsection
resources/views/roles/show.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h1>{{ ucfirst($role->name) }} Role</h1>
<div class="lead">
</div>
<div class="container mt-4">
<h3>Assigned permissions</h3>
<table class="table table-striped">
<thead>
<th scope="col" width="20%">Name</th>
<th scope="col" width="1%">Guard</th>
</thead>
@foreach($rolePermissions as $permission)
<tr>
<td>{{ $permission->name }}</td>
<td>{{ $permission->guard_name }}</td>
</tr>
@endforeach
</table>
</div>
</div>
<div class="mt-4">
<a href="{{ route('roles.edit', $role->id) }}" class="btn btn-info">Edit</a>
<a href="{{ route('roles.index') }}" class="btn btn-default">Back</a>
</div>
@endsection
resources/views/users/create.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h1>Add new user</h1>
<div class="lead">
Add new user and assign role.
</div>
<div class="container mt-4">
<form method="POST" action="">
@csrf
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input value="{{ old('name') }}"
type="text"
class="form-control"
name="name"
placeholder="Name" required>
@if ($errors->has('name'))
<span class="text-danger text-left">{{ $errors->first('name') }}</span>
@endif
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input value="{{ old('email') }}"
type="email"
class="form-control"
name="email"
placeholder="Email address" required>
@if ($errors->has('email'))
<span class="text-danger text-left">{{ $errors->first('email') }}</span>
@endif
</div>
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input value="{{ old('username') }}"
type="text"
class="form-control"
name="username"
placeholder="Username" required>
@if ($errors->has('username'))
<span class="text-danger text-left">{{ $errors->first('username') }}</span>
@endif
</div>
<button type="submit" class="btn btn-primary">Save user</button>
<a href="{{ route('users.index') }}" class="btn btn-default">Back</a>
</form>
</div>
</div>
@endsection
resources/views/users/edit.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h1>Update user</h1>
<div class="lead">
</div>
<div class="container mt-4">
<form method="post" action="{{ route('users.update', $user->id) }}">
@method('patch')
@csrf
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input value="{{ $user->name }}"
type="text"
class="form-control"
name="name"
placeholder="Name" required>
@if ($errors->has('name'))
<span class="text-danger text-left">{{ $errors->first('name') }}</span>
@endif
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input value="{{ $user->email }}"
type="email"
class="form-control"
name="email"
placeholder="Email address" required>
@if ($errors->has('email'))
<span class="text-danger text-left">{{ $errors->first('email') }}</span>
@endif
</div>
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input value="{{ $user->username }}"
type="text"
class="form-control"
name="username"
placeholder="Username" required>
@if ($errors->has('username'))
<span class="text-danger text-left">{{ $errors->first('username') }}</span>
@endif
</div>
<div class="mb-3">
<label for="role" class="form-label">Role</label>
<select class="form-control"
name="role" required>
<option value="">Select role</option>
@foreach($roles as $role)
<option value="{{ $role->id }}"
{{ in_array($role->name, $userRole)
? 'selected'
: '' }}>{{ $role->name }}</option>
@endforeach
</select>
@if ($errors->has('role'))
<span class="text-danger text-left">{{ $errors->first('role') }}</span>
@endif
</div>
<button type="submit" class="btn btn-primary">Update user</button>
<a href="{{ route('users.index') }}" class="btn btn-default">Cancel</button>
</form>
</div>
</div>
@endsection
resources/views/users/index.blade.php
@extends('layouts.app-master')
@section('content')
<h1 class="mb-3">Laravel 8 User Roles and Permissions Step by Step Tutorial - codeanddeploy.com</h1>
<div class="bg-light p-4 rounded">
<h1>Users</h1>
<div class="lead">
Manage your users here.
<a href="{{ route('users.create') }}" class="btn btn-primary btn-sm float-right">Add new user</a>
</div>
<div class="mt-2">
@include('layouts.partials.messages')
</div>
<table class="table table-striped">
<thead>
<tr>
<th scope="col" width="1%">#</th>
<th scope="col" width="15%">Name</th>
<th scope="col">Email</th>
<th scope="col" width="10%">Username</th>
<th scope="col" width="10%">Roles</th>
<th scope="col" width="1%" colspan="3"></th>
</tr>
</thead>
<tbody>
@foreach($users as $user)
<tr>
<th scope="row">{{ $user->id }}</th>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>{{ $user->username }}</td>
<td>
@foreach($user->roles as $role)
<span class="badge bg-primary">{{ $role->name }}</span>
@endforeach
</td>
<td><a href="{{ route('users.show', $user->id) }}" class="btn btn-warning btn-sm">Show</a></td>
<td><a href="{{ route('users.edit', $user->id) }}" class="btn btn-info btn-sm">Edit</a></td>
<td>
{!! Form::open(['method' => 'DELETE','route' => ['users.destroy', $user->id],'style'=>'display:inline']) !!}
{!! Form::submit('Delete', ['class' => 'btn btn-danger btn-sm']) !!}
{!! Form::close() !!}
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="d-flex">
{!! $users->links() !!}
</div>
</div>
@endsection
resources/views/users/show.blade.php
@extends('layouts.app-master')
@section('content')
<div class="bg-light p-4 rounded">
<h1>Show user</h1>
<div class="lead">
</div>
<div class="container mt-4">
<div>
Name: {{ $user->name }}
</div>
<div>
Email: {{ $user->email }}
</div>
<div>
Username: {{ $user->username }}
</div>
</div>
</div>
<div class="mt-4">
<a href="{{ route('users.edit', $user->id) }}" class="btn btn-info">Edit</a>
<a href="{{ route('users.index') }}" class="btn btn-default">Back</a>
</div>
@endsection
Шаг 10: Создайте команду
Далее мы создадим команду для генерации разрешений laravel, используя имя маршрута. Запустите приведенную ниже команду:
php artisan make:command CreateRoutePermissionsCommand
Перейдите в AppConsoleCommandsCreateRoutePermissionsCommand.php и скопируйте код ниже:
<?php
namespace AppConsoleCommands;
use IlluminateConsoleCommand;
use IlluminateSupportFacadesRoute;
use SpatiePermissionModelsPermission;
class CreateRoutePermissionsCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'permission:create-permission-routes';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a permission routes.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$routes = Route::getRoutes()->getRoutes();
foreach ($routes as $route) {
if ($route->getName() != '' && $route->getAction()['middleware']['0'] == 'web') {
$permission = Permission::where('name', $route->getName())->first();
if (is_null($permission)) {
permission::create(['name' => $route->getName()]);
}
}
}
$this->info('Permission routes added successfully.');
}
}
Затем запустим созданную команду:
php artisan permission:create-permission-routes
ПРИМЕЧАНИЕ: Если вы уже работаете в продакшене, пожалуйста, добавьте планировщик для этой команды, чтобы вам не нужно было запускать ее вручную.
Шаг 11: Добавление пользователя Admin Seeder
Далее мы должны добавить пользователя по умолчанию под именем admin, чтобы вы могли получить доступ к системе с созданным пользователем по умолчанию.
Выполните следующую команду:
php artisan make:seeder CreateAdminUserSeeder
Затем перейдите*DatabaseSeedersCreateAdminUserSeeder.php* и скопируйте приведенный ниже код:
<?php
namespace DatabaseSeeders;
use AppModelsUser;
use IlluminateDatabaseSeeder;
use SpatiePermissionModelsRole;
use SpatiePermissionModelsPermission;
class CreateAdminUserSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$user = User::create([
'name' => 'Admin',
'email' => 'admin@gmail.com',
'username' => 'admin',
'password' => 'admin123'
]);
$role = Role::create(['name' => 'admin']);
$permissions = Permission::pluck('id','id')->all();
$role->syncPermissions($permissions);
$user->assignRole([$role->id]);
}
}
Затем выполните следующую команду:
php artisan db:seed --class=CreateAdminUserSeeder
Теперь у вас есть администратор, которого вы можете использовать для входа и тестирования ролей и прав пользователей Laravel 8 ACL.
Теперь вы готовы. Выполните следующую команду для тестирования.
php artisan serve
Затем зайдите в браузер:
http://127.0.0.1:8000
Не забудьте, что ваши учетные данные:
email: admin
пароль: admin123
Надеюсь, этот учебник поможет вам. Посетите здесь https://codeanddeploy.com/blog/laravel/laravel-8-user-roles-and-permissions-step-by-step-tutorial, если хотите скачать этот код.
Счастливого кодирования 🙂