###What We'll Build When building an application, we often need to set up an access control list (ACL). An ACL specifies the level of permission granted to a user of an application. For example a user John may have the permission to read and write to a resource while another user Smith may have the permission only to read the resource.
###我们将构建的内容构建应用程序时,我们通常需要设置访问控制列表(ACL)。 ACL指定授予应用程序用户的权限级别。 例如,用户John可能具有读取和写入资源的权限,而另一个用户Smith可能仅具有读取资源的权限。
In this tutorial, I will teach you how to add access control to a Laravel app using Laravel-permission package. For this tutorial we will build a simple blog application where users can be assigned different levels of permission. Our user admin page will look like this:
在本教程中,我将教您如何使用Laravel-permission软件包向Laravel应用添加访问控制。 在本教程中,我们将构建一个简单的博客应用程序,可以为用户分配不同级别的权限。 我们的用户管理页面如下所示:
###Why Use Laravel-Permission
###为什么使用Laravel-Permission
The Laravel-Permission package is built on top of Laravel's authorization features introduced in the 5.1.1 release. Although there are other packages that claim to offer similar functionalities, none of them have the same level of activity and maintenance as the laravel-permission package.
Laravel-Permission软件包建立在5.1.1版本中引入的Laravel授权功能的基础上。 尽管还有其他声称提供类似功能的软件包,但它们都没有与laravel-permission软件包具有相同级别的活动和维护。
###Development Environment and Installation You can get Laravel up and running by first downloading the installer
###开发环境和安装您可以通过首先下载安装程序来启动和运行Laravel
composer global require"laravel/installer"
Then add $HOME/.composer/vendor/bin
to your $PATH so the laravel
executable can be located by your system. Now you can install the latest stable version of Laravel by running
然后将$HOME/.composer/vendor/bin
到$ PATH中,以便系统可以找到laravel
可执行文件。 现在,您可以通过运行以下命令来安装Laravel的最新稳定版本
laravel new
To install the laravel-permission package run
要安装laravel-permission软件包,请运行
composer require spatie/laravel-permission
Next include the package to our list of service providers, in config/app.php
add Spatie\Permission\PermissionServiceProvider::class
so our file looks like this
接下来,将该包包含到我们的服务提供商列表中,在config/app.php
添加Spatie\Permission\PermissionServiceProvider::class
以便我们的文件如下所示
'providers' => [
...
Spatie\Permission\PermissionServiceProvider::class,
];
Next publish the migration file for this package with the command
接下来,使用以下命令发布此软件包的迁移文件
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"
数据库设置和迁移 (Database Setup and Migrations)
Next create the database and update the .env
file to include the database information. For example, for this tutorial the database information section of the .env
looks like this:
接下来,创建数据库并更新.env
文件以包括数据库信息。 例如,对于本教程, .env
的数据库信息部分如下所示:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=acl4
DB_USERNAME=root
DB_PASSWORD=
To build the tables, run
要构建表,请运行
php artisan migrate
Please note that in Laravel 5.4 the default character set is changed to utf8mb4, therefore if you are running MariaDB or MYSQL version lower than 5.7.7 you may get this error when trying to run migration files
请注意,在Laravel 5.4中,默认字符集更改为utf8mb4,因此,如果您运行的MariaDB或MYSQL版本低于5.7.7,则在尝试运行迁移文件时可能会出现此错误。
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table users add unique users_email_unique(email))
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
To fix this error edit the app\Providers\AppServiceProvider.php
file, setting the default string length in the boot method
要解决此错误,请编辑app\Providers\AppServiceProvider.php
文件,并在启动方法中设置默认字符串长度
use Illuminate\Support\Facades\Schema;
public function boot()
{
Schema::defaultStringLength(191);
}
After that run the migration again. If it works as normal you would find the following tables in your database:
之后,再次运行迁移。 如果正常运行,您将在数据库中找到以下表格:
migrations
: This keeps track of migration process that have ranmigrations
:跟踪已执行的迁移过程users
: This holds the users data of the applicationusers
:保存应用程序的用户数据password_resets
: Holds token information when users request a new passwordpassword_resets
:在用户请求新密码时保存令牌信息permissions
: This holds the various permissions needed in the applicationpermissions
:拥有应用程序所需的各种权限roles
: This holds the roles in our applicationroles
:这在我们的应用程序中拥有角色role_has_permission
: This is a pivot table that holds relationship information between the permissions table and the role tablerole_has_permission
:这是一个数据透视表,其中包含权限表和角色表之间的关系信息user_has_roles
: Also a pivot table, holds relationship information between the roles and the users table.user_has_roles
:也是数据透视表,其中包含角色和用户表之间的关系信息。user_has_permissions
: Also a pivot table, holds relationship information between the users table and the permissions table.user_has_permissions
:也是数据透视表,用于保存用户表和权限表之间的关系信息。
Publish the configuration file for this package by running
通过运行发布此程序包的配置文件
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"
The config file allows us to set the location of the Eloquent model of the permission and role class. You can also manually set the table names that should be used to retrieve your roles and permissions. Next we need to add the HasRoles
trait to the User model:
配置文件允许我们设置权限和角色类的Eloquent模型的位置。 您还可以手动设置应用于检索角色和权限的表名。 接下来,我们需要将HasRoles
特性添加到User模型:
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable {
use HasRoles;
// ...
}
Laravel集体HTML表单构建器 (Laravel Collective HTML Form builder)
Next install Laravel Collective HTML Form builder as this will be useful further on when we are creating our forms:
下一步安装Laravel Collective HTML Form构建器,因为这将在我们创建表单时进一步有用:
composer require laravelcollective/html
Then add your new provider to the providers array of config/app.php
:
然后将您的新提供程序添加到config/app.php
的providers数组config/app.php
:
'providers' => [
...
Collective\Html\HtmlServiceProvider::class,
];
Finally, add two class aliases to the aliases array of config/app.php
:
最后,将两个类别名添加到config/app.php
的aliases数组config/app.php
:
'aliases' => [
// ...
'Form' => Collective\Html\FormFacade::class,
'Html' => Collective\Html\HtmlFacade::class,
// ...
],
That's all the installation and configuration needed. A role can be created like a regular Eloquent model, like this:
这就是所需的所有安装和配置。 可以像常规的Eloquent模型一样创建角色,如下所示:
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
$role = Role::create(['name' => 'writer']);
$permission = Permission::create(['name' => 'edit articles']);
You can also get the permissions associated to a user like this:
您还可以像这样获得与用户相关联的权限:
$permissions = $user->permissions;
And using the pluck method, pluck()
you can get the role names associated with a user like this:
使用pluck方法pluck()
可以获得与用户相关的角色名称,如下所示:
$roles = $user->roles()->pluck('name');
Other methods available to us include:
我们可以使用的其他方法包括:
givePermissionTo()
: Allows us to give persmission to a user or rolegivePermissionTo()
:允许我们授予用户或角色权限revokePermissionTo()
: Revoke permission from a user or rolerevokePermissionTo()
:撤消用户或角色的权限hasPermissionTo()
: Check if a user or role has a given permissionhasPermissionTo()
:检查用户或角色是否具有给定的权限assignRole()
: Assigns role to a userassignRole()
:向用户分配角色removeRole()
: Removes role from a userremoveRole()
:从用户删除角色hasRole()
: Checks if a user has a rolehasRole()
:检查用户是否具有角色hasAnyRole(Role::all())
: Checks if a user has any of a given list of roleshasAnyRole(Role::all())
:检查用户是否具有给定的角色列表中的任何一个hasAllRoles(Role::all())
: Checks if a user has all of a given list of rolehasAllRoles(Role::all())
:检查用户是否具有角色的所有给定列表
The methods assignRole
, hasRole
, hasAnyRole
, hasAllRoles
and removeRole
can accept a string, a Spatie\Permission\Models\Role-object
or an \Illuminate\Support\Collection
object. The givePermissionTo
and revokePermissionTo
methods can accept a string or a Spatie\Permission\Models\Permission
object.
方法assignRole
, hasRole
, hasAnyRole
, hasAllRoles
和removeRole
可以接受字符串, Spatie\Permission\Models\Role-object
或\Illuminate\Support\Collection
对象。 givePermissionTo
和revokePermissionTo
方法可以接受字符串或Spatie\Permission\Models\Permission
对象。
Laravel-Permission also allows to use Blade directives to verify if the logged in user has all or any of a given list of roles:
Laravel-Permission还允许使用Blade指令来验证登录用户是否具有全部或任何给定角色列表:
@role('writer')
I'm a writer!
@else
I'm not a writer...
@endrole
@hasrole('writer')
I'm a writer!
@else
I'm not a writer...
@endhasrole
@hasanyrole(Role::all())
I have one or more of these roles!
@else
I have none of these roles...
@endhasanyrole
@hasallroles(Role::all())
I have all of these roles!
@else
I don't have all of these roles...
@endhasallroles
The Blade directives above depends on the users role. Sometimes we need to check directly in our view if a user has a certain permission. You can do that using Laravel's native @can
directive:
上面的Blade指令取决于用户角色。 有时我们需要直接在我们的视图中检查用户是否具有一定的权限。 您可以使用Laravel的本机@can
指令执行此操作:
@can('Edit Post')
I have permission to edit
@endcan
###Controllers, Authentication and Views
###控制器,身份验证和视图
You will need a total of four controllers for this application. Let's use resource controllers, as this automatically adds stub methods for us. Our controllers will be called
此应用程序总共需要四个控制器。 让我们使用资源控制器,因为这会自动为我们添加存根方法。 我们的控制器将被称为
- PostController 后控制器
- UserController 用户控制器
- RoleController 角色控制器
- PermissionController PermissionController
Before working on these controllers let's create our authentication system. With one command Laravel provides a quick way to scaffold all of the routes and views needed for authentication.
在使用这些控制器之前,让我们创建身份验证系统。 Laravel使用一条命令提供了一种快速的方法来搭建身份验证所需的所有路径和视图。
php artisan make:auth
After running this command you would notice two new links for user login and registration in the home page.
运行此命令后,您会在主页中看到两个用于用户登录和注册的新链接。
This command also creates a HomeController
(you can delete this as it won't be needed), a resources/views/layouts/app.blade.php
file which contains markup that would be shared by all our views and an app/Http/Controllers/Auth
directory which contains the controllers for registration and login. Switch into this directory and open the RegisterController.php
file. Remove the bcrypt
function in the create
method, so the the method looks like this
此命令还会创建一个HomeController
(您可以删除它,因为它不需要它),一个resources/views/layouts/app.blade.php
文件,其中包含将由我们所有视图共享的标记以及一个app/Http/Controllers/Auth
目录,其中包含用于注册和登录的控制器。 切换到该目录并打开RegisterController.php
文件。 在create
方法中删除bcrypt
函数,因此该方法如下所示
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => $data['password'],
]);
}
Instead let's define a mutator in app\User.php
which would encrypt all our password fields. In app\User.php
add this method:
相反,让我们在app\User.php
定义一个app\User.php
,该app\User.php
将对我们所有的密码字段进行加密。 在app\User.php
添加以下方法:
public function setPasswordAttribute($password)
{
$this->attributes['password'] = bcrypt($password);
}
This would provide the same functionality as before but now you don't need to write the bcrypt
function when dealing with the password field in subsequent controllers.
这将提供与以前相同的功能,但是现在您在处理后续控制器中的password字段时无需编写bcrypt
函数。
Also in the RegisterController.php
file. Change the $redirectTo
property to:
同样在RegisterController.php
文件中。 将$redirectTo
属性更改为:
protected $redirectTo = '/';
Do the same thing in the LoginController.php
file.
在LoginController.php
文件中执行相同的操作。
Since the HomeController
has been deleted our users are now redirected to the home page which would contain a list of our blog posts.
由于已删除HomeController
,因此我们现在将用户重定向到主页,该主页将包含我们的博客文章列表。
Next let's edit the resources/views/layouts/app.blade.php
file to include: an extra drop-down 'Admin' link to view all users and an errors file which checks if our form produced any error. The 'Admin' link would only be viewed by users with the 'Admin' Role. We would also create a custom styles.css
which would have extra styling for our resources/views/posts/index.blade.php
view. The styling is just a paragraph in the teaser of our index view, the file should be located in public/css/styles.css
接下来,让我们编辑resources/views/layouts/app.blade.php
文件以包括:一个额外的下拉“ Admin”链接以查看所有用户,以及一个错误文件,该文件检查我们的表单是否产生任何错误。 只有具有“管理员”角色的用户才能查看“管理员”链接。 我们还将创建一个自定义的styles.css
,它将为我们的resources/views/posts/index.blade.php
视图提供额外的样式。 样式只是索引视图预告片中的一个段落,文件应位于public/css/styles.css
{{-- resources/views/layouts/app.blade.php --}}<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<link href="{{ asset('css/styles.css') }}" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Scripts -->
<script>
window.Laravel = {!! json_encode([
'csrfToken' => csrf_token(),
]) !!};
</script>
<script src="https://use.fontawesome.com/9712be8772.js"></script>
</head>
<body>
<div id="app">
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<!-- Collapsed Hamburger -->
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#app-navbar-collapse">
<span class="sr-only">Toggle Navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- Branding Image -->
<a class="navbar-brand" href="{{ url('/') }}">
{{ config('app.name', 'Laravel') }}
</a>
</div>
<div class="collapse navbar-collapse" id="app-navbar-collapse">
<!-- Left Side Of Navbar -->
<ul class="nav navbar-nav">
<li><a href="{{ url('/') }}">Home</a></li>
@if (!Auth::guest())
<li><a href="{{ route('posts.create') }}">New Article</a></li>
@endif
</ul>
<!-- Right Side Of Navbar -->
<ul class="nav navbar-nav navbar-right">
<!-- Authentication Links -->
@if (Auth::guest())
<li><a href="{{ route('login') }}">Login</a></li>
<li><a href="{{ route('register') }}">Register</a></li>
@else
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
{{ Auth::user()->name }} <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li>
@role('Admin') {{-- Laravel-permission blade helper --}}
<a href="#"><i class="fa fa-btn fa-unlock"></i>Admin</a>
@endrole
<a href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
Logout
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
{{ csrf_field() }}
</form>
</li>
</ul>
</li>
@endif
</ul>
</div>
</div>
</nav>
@if(Session::has('flash_message'))
<div class="container">
<div class="alert alert-success"><em> {!! session('flash_message') !!}</em>
</div>
</div>
@endif
<div class="row">
<div class="col-md-8 col-md-offset-2">
@include ('errors.list') {{-- Including error file --}}
</div>
</div>
@yield('content')
</div>
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
The error file is:
错误文件是:
{{-- resources\views\errors\list.blade.php --}}
@if (count($errors) > 0)<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
and the styles.css
file is simply:
并且styles.css
文件很简单:
p.teaser {
text-indent: 30px;
}
###Post Controller
### Post Controller
First, let's create the migration and model files for the PostController
首先,让我们为PostController
创建迁移和模型文件
php artisan make:model Post -m
This command generates a migration file in app/database/migrations
for generating a new MySQL table named posts in our database and a model file Post.php
in the app
directory. Let's edit the migration file to include title and body fields of our post. Add a title and body field so the migration file looks like this:
此命令在app/database/migrations
生成一个迁移文件,用于在我们的数据库中生成名为MySQL的新MySQL表,并在app
目录中生成模型文件Post.php
。 让我们编辑迁移文件以包含帖子的标题和正文字段。 添加标题和正文字段,以便迁移文件如下所示:
<?php
//database\migrations\xxxx_xx_xx_xxxxxx_create_posts_table.php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
After saving the file, run migration again
保存文件后,再次运行迁移
php artisan migrate
You can now check the database for the post
table and columns.
现在,您可以检查数据库中的post
表和列。
Next make the title and body field of the Post
model mass assignable
接下来,使Post
模型的标题和正文字段可分配
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model {
protected $fillable = [
'title', 'body'
];
}
Now let's generate our resource controller.
现在,让我们生成资源控制器。
php artisan make:controller PostController --resource
This will create our controller with all the stub methods needed. Edit this file to look like this
这将创建具有所需所有存根方法的控制器。 编辑此文件以使其看起来像这样
<?php
// app/Http/Controllers/PostController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
use Auth;
use Session;
class PostController extends Controller {
public function __construct() {
$this->middleware(['auth', 'clearance'])->except('index', 'show');
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index() {
$posts = Post::orderby('id', 'desc')->paginate(5); //show only 5 items at a time in descending order
return view('posts.index', compact('posts'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create() {
return view('posts.create');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
//Validating title and body field
$this->validate($request, [
'title'=>'required|max:100',
'body' =>'required',
]);
$title = $request['title'];
$body = $request['body'];
$post = Post::create($request->only('title', 'body'));
//Display a successful message upon save
return redirect()->route('posts.index')
->with('flash_message', 'Article,
'. $post->title.' created');
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id) {
$post = Post::findOrFail($id); //Find post of id = $id
return view ('posts.show', compact('post'));
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id) {
$post = Post::findOrFail($id);
return view('posts.edit', compact('post'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id) {
$this->validate($request, [
'title'=>'required|max:100',
'body'=>'required',
]);
$post = Post::findOrFail($id);
$post->title = $request->input('title');
$post->body = $request->input('body');
$post->save();
return redirect()->route('posts.show',
$post->id)->with('flash_message',
'Article, '. $post->title.' updated');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id) {
$post = Post::findOrFail($id);
$post->delete();
return redirect()->route('posts.index')
->with('flash_message',
'Article successfully deleted');
}
}
Here the Post
class was imported from our model and the Auth
class which was generated with the make:auth
command earlier. These were imported so that you would be able to make Eloquent queries on the Post
table and so as to be able to have access to authentication information of our users. In the constructor two middlewares were called, one is auth
which restricts access to the PostController
methods to authenticated users the other is a custom middleware is yet to be created. This would be responsible for our Permissions and Roles system. Next, index
and show
are passed into the except method to allow all users to be able to view posts.
在这里, Post
类是从我们的模型中导入的,而Auth
类是之前使用make:auth
命令生成的。 这些是导入的,以便您能够在Post
表上进行口才查询,并能够访问我们用户的身份验证信息。 在构造函数中,调用了两个中间件,一个是auth
,它将对PostController
方法的访问限制为已认证的用户,另一个是尚未创建的自定义中间件。 这将负责我们的“权限和角色”系统。 接下来,将index
和show
传递到except方法中,以允许所有用户查看帖子。
The index()
method lists all the available posts. It queries the post
table for all posts and passes this information to the view. Paginate()
allows us to limit the number of posts in a page, in this case five.
index()
方法列出了所有可用的帖子。 它查询post
表中的所有帖子,并将此信息传递到视图。 Paginate()
允许我们限制页面中的帖子数量,在这种情况下为五个。
The create()
method simply returns the posts/create
view which would contain a form for creating new posts. The store()
method saves the information input from the posts/create
view. The information is first validated and after it is saved, a flash message is passed to the view posts/index
.
create()
方法仅返回posts/create
视图,其中将包含用于创建新帖子的表单。 store()
方法保存从posts/create
视图输入的信息。 信息首先经过验证,然后保存,然后将一条简短消息传递到view posts/index
。
Our show()
method of the PostController
allows us to display a single post. This method takes the post
id as an argument and passes it to the method Post::find()
. The result of the query is then sent to our posts/show
view.
PostController
show()
方法允许我们显示单个帖子。 此方法将post
id作为参数,并将其传递给方法Post::find()
。 查询的结果然后发送到我们的posts/show
视图。
The edit()
method, similar to the create()
method simply returns the posts/edit
view which would contain a form for creating editing posts. The update()
method takes the information from the posts/edit
view and updates the record. The destroy()
method let's us delete a post.
与create()
方法类似, edit()
方法仅返回posts/edit
视图,其中将包含用于创建编辑帖子的表单。 update()
方法从posts/edit
视图中获取信息并更新记录。 destroy()
方法让我们删除帖子。
Now that you have the PostController
you need to set up the routes. Edit your app/routes/web.php
file to look like this:
现在有了PostController
您需要设置路由。 编辑您的app/routes/web.php
文件,如下所示:
<?php
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/', 'PostController@index')->name('home');
Route::resource('users', 'UserController');
Route::resource('roles', 'RoleController');
Route::resource('permissions', 'PermissionController');
Route::resource('posts', 'PostController');
The /
route is the route to our home page, here it was renamed to home
The Auth
route was generated when you ran the make:auth
command. It handles authentication related routes. The other four routes are for resources that would be created later.
该/
路线是我们的主页的路线,这里更名为home
的Auth
,当您运行生成路线make:auth
命令。 它处理与身份验证相关的路由。 其他四个路由用于稍后创建的资源。
###Post Views
###发布视图
Only four views are needed for our PostController
. Create the files \resources\views\posts\index.blade.php
, \resources\views\posts\create.blade.php
, \resources\views\posts\show.blade.php
, \resources\views\posts\edit.blade.php
PostController
仅需要四个视图。 创建文件\resources\views\posts\index.blade.php
, \resources\views\posts\create.blade.php
, \resources\views\posts\show.blade.php
, \resources\views\posts\edit.blade.php
Edit the index.blade.php
file to look like this
编辑index.blade.php
文件,如下所示
@extends('layouts.app')
@section('content')<div class="container">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-default">
<div class="panel-heading"><h3>Posts</h3></div>
<div class="panel-heading">Page {{ $posts->currentPage() }} of {{ $posts->lastPage() }}</div>
@foreach ($posts as $post)
<div class="panel-body">
<li style="list-style-type:disc">
<a href="{{ route('posts.show', $post->id ) }}"><b>{{ $post->title }}</b><br>
<p class="teaser">
{{ str_limit($post->body, 100) }} {{-- Limit teaser to 100 characters --}}
</p>
</a>
</li>
</div>
@endforeach
</div>
<div class="text-center">
{!! $posts->links() !!}
</div>
</div>
</div>
</div>
@endsection
Notice that this file extends views\layouts\app.php
file, which was generated earlier by the make:auth
command.
请注意,该文件扩展了views\layouts\app.php
文件,该文件先前是由make:auth
命令生成的。
The create.blade.php
file looks like this
create.blade.php
文件如下所示
@extends('layouts.app')
@section('title', '| Create New Post')
@section('content')<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1>Create New Post</h1>
<hr>
{{-- Using the Laravel HTML Form Collective to create our form --}}
{{ Form::open(array('route' => 'posts.store')) }}
<div class="form-group">
{{ Form::label('title', 'Title') }}
{{ Form::text('title', null, array('class' => 'form-control')) }}
<br>
{{ Form::label('body', 'Post Body') }}
{{ Form::textarea('body', null, array('class' => 'form-control')) }}
<br>
{{ Form::submit('Create Post', array('class' => 'btn btn-success btn-lg btn-block')) }}
{{ Form::close() }}
</div>
</div>
</div>
@endsection
The show
view looks like this:
show
视图如下所示:
@extends('layouts.app')
@section('title', '| View Post')
@section('content')<div class="container">
<h1>{{ $post->title }}</h1>
<hr>
<p class="lead">{{ $post->body }} </p>
<hr>
{!! Form::open(['method' => 'DELETE', 'route' => ['posts.destroy', $post->id] ]) !!}
<a href="{{ url()->previous() }}" class="btn btn-primary">Back</a>
@can('Edit Post')
<a href="{{ route('posts.edit', $post->id) }}" class="btn btn-info" role="button">Edit</a>
@endcan
@can('Delete Post')
{!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}
@endcan
{!! Form::close() !!}
</div>
@endsection
Here the can
directive checks if a user has the permission to Edit or Delete Posts, if so the Edit and Delete button will be displayed. If the user does not have these permissions, only the Back button would be displayed.
这里的can
指令检查用户是否具有“编辑或删除帖子”的权限,如果是,则将显示“编辑和删除”按钮。 如果用户没有这些权限,则仅显示“后退”按钮。
The edit
view just displays a edit form that will be used to update records:
edit
视图仅显示将用于更新记录的编辑表单:
@extends('layouts.app')
@section('title', '| Edit Post')
@section('content')<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1>Edit Post</h1>
<hr>
{{ Form::model($post, array('route' => array('posts.update', $post->id), 'method' => 'PUT')) }}
<div class="form-group">
{{ Form::label('title', 'Title') }}
{{ Form::text('title', null, array('class' => 'form-control')) }}<br>
{{ Form::label('body', 'Post Body') }}
{{ Form::textarea('body', null, array('class' => 'form-control')) }}<br>
{{ Form::submit('Save', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
</div>
</div>
</div>
@endsection
If you visit the home page you would see this
如果您访问主页,则会看到此信息
###User Controller The UserController
will handle displaying all users, creating of new users, editing users, assigning roles to users and deleting users. As before generate the controller by running
### User Controller UserController
将显示所有用户,创建新用户,编辑用户,为用户分配角色以及删除用户。 和以前一样,通过运行生成控制器
php artisan make:controller UserController --resource
Then replace the content of this file with:
然后将该文件的内容替换为:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Auth;
//Importing laravel-permission models
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
//Enables us to output flash messaging
use Session;
class UserController extends Controller {
public function __construct() {
$this->middleware(['auth', 'isAdmin']); //isAdmin middleware lets only users with a //specific permission permission to access these resources
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index() {
//Get all users and pass it to the view
$users = User::all();
return view('users.index')->with('users', $users);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create() {
//Get all roles and pass it to the view
$roles = Role::get();
return view('users.create', ['roles'=>$roles]);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
//Validate name, email and password fields
$this->validate($request, [
'name'=>'required|max:120',
'email'=>'required|email|unique:users',
'password'=>'required|min:6|confirmed'
]);
$user = User::create($request->only('email', 'name', 'password')); //Retrieving only the email and password data
$roles = $request['roles']; //Retrieving the roles field
//Checking if a role was selected
if (isset($roles)) {
foreach ($roles as $role) {
$role_r = Role::where('id', '=', $role)->firstOrFail();
$user->assignRole($role_r); //Assigning role to user
}
}
//Redirect to the users.index view and display message
return redirect()->route('users.index')
->with('flash_message',
'User successfully added.');
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id) {
return redirect('users');
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id) {
$user = User::findOrFail($id); //Get user with specified id
$roles = Role::get(); //Get all roles
return view('users.edit', compact('user', 'roles')); //pass user and roles data to view
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id) {
$user = User::findOrFail($id); //Get role specified by id
//Validate name, email and password fields
$this->validate($request, [
'name'=>'required|max:120',
'email'=>'required|email|unique:users,email,'.$id,
'password'=>'required|min:6|confirmed'
]);
$input = $request->only(['name', 'email', 'password']); //Retreive the name, email and password fields
$roles = $request['roles']; //Retreive all roles
$user->fill($input)->save();
if (isset($roles)) {
$user->roles()->sync($roles); //If one or more role is selected associate user to roles
}
else {
$user->roles()->detach(); //If no role is selected remove exisiting role associated to a user
}
return redirect()->route('users.index')
->with('flash_message',
'User successfully edited.');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id) {
//Find a user with a given id and delete
$user = User::findOrFail($id);
$user->delete();
return redirect()->route('users.index')
->with('flash_message',
'User successfully deleted.');
}
}
Here the User
class, the Role
class, the Permission
class and the Auth
class are imported. In the constructor the auth
middleware is called to make sure only authenticated users have access to the User resource. A custom middleware isAdmin
is also called. This checks if the authenticated user has administrator privileges. This middleware will be created later.
这里,导入了User
类, Role
类, Permission
类和Auth
类。 在构造函数中,将调用auth
中间件,以确保只有经过身份验证的用户才能访问User资源。 还调用自定义中间件isAdmin
。 这将检查通过身份验证的用户是否具有管理员特权。 稍后将创建此中间件。
The index()
method gets all users from the Users table and passes it to the index view which will display all users in a table. The create()
method first gets all the Roles from the Roles table and passes it to the create view. This is so that Roles can be added when creating a User.
index()
方法从Users表中获取所有用户,并将其传递到索引视图,该视图将在表中显示所有用户。 首先, create()
方法从Roles表中获取所有Roles并将其传递给create视图。 这样,可以在创建用户时添加角色。
The store()
method saves the input from the create view, after validating the input, looping through the Roles that was passed in the form and assigning these Roles to the User. The show()
method just redirects back to the users page as for this demonstration, we wont need to show each user individually.
在验证输入,遍历表单中传递的角色并将这些角色分配给用户之后, store()
方法将保存来自创建视图的输入。 show()
方法只是重定向回到用户页面,如本演示所示,我们不需要分别显示每个用户。
The edit()
method gets the user corresponding to the id passed, then gets all roles
and passes it to the edit view. The update()
method validates data from the edit view and saves the updated name and password fields. It gets all roles
from the roles
table and while looping through them, removes any role
assign to the user. It then takes the role
data inputted from the form, matches them with the values in the databases and assigns these roles
to the user.
edit()
方法获取与传递的ID相对应的用户,然后获取所有roles
并将其传递给Edit视图。 update()
方法从编辑视图验证数据并保存更新的名称和密码字段。 它从roles
表中获取所有roles
,并在循环浏览它们时,删除分配给用户的任何role
。 然后,它将接受从表单输入的role
数据,将其与数据库中的值进行匹配,然后将这些roles
分配给用户。
The destroy()
method allows us to delete a user
along with it's corresponding role
.
destroy()
方法允许我们删除user
及其相应role
。
###User Views
###用户视图
Three views are needed here: index
, create
and edit
views. The index
view would contain a table that lists all our users
and their roles
.
这里需要三个视图: index
, create
和edit
视图。 index
视图将包含一个列出所有users
及其roles
。
{{-- \resources\views\users\index.blade.php --}}
@extends('layouts.app')
@section('title', '| Users')
@section('content')<div class="col-lg-10 col-lg-offset-1">
<h1><i class="fa fa-users"></i> User Administration <a href="{{ route('roles.index') }}" class="btn btn-default pull-right">Roles</a>
<a href="{{ route('permissions.index') }}" class="btn btn-default pull-right">Permissions</a></h1>
<hr>
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Date/Time Added</th>
<th>User Roles</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
@foreach ($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>{{ $user->created_at->format('F d, Y h:ia') }}</td>
<td>{{ $user->roles()->pluck('name')->implode(' ') }}</td>{{-- Retrieve array of roles associated to a user and convert to string --}}
<td>
<a href="{{ route('users.edit', $user->id) }}" class="btn btn-info pull-left" style="margin-right: 3px;">Edit</a>
{!! Form::open(['method' => 'DELETE', 'route' => ['users.destroy', $user->id] ]) !!}
{!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}
{!! Form::close() !!}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<a href="{{ route('users.create') }}" class="btn btn-success">Add User</a>
</div>
@endsection
The create
view is just a form that allows us to create new users
and assign roles
to them.
create
视图只是一种允许我们创建新users
并为其分配roles
的表格。
{{-- \resources\views\users\create.blade.php --}}
@extends('layouts.app')
@section('title', '| Add User')
@section('content')<div class='col-lg-4 col-lg-offset-4'>
<h1><i class='fa fa-user-plus'></i> Add User</h1>
<hr>
{{ Form::open(array('url' => 'users')) }}
<div class="form-group">
{{ Form::label('name', 'Name') }}
{{ Form::text('name', '', array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('email', 'Email') }}
{{ Form::email('email', '', array('class' => 'form-control')) }}
</div>
<div class='form-group'>
@foreach ($roles as $role)
{{ Form::checkbox('roles[]', $role->id ) }}
{{ Form::label($role->name, ucfirst($role->name)) }}<br>
@endforeach
</div>
<div class="form-group">
{{ Form::label('password', 'Password') }}<br>
{{ Form::password('password', array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('password', 'Confirm Password') }}<br>
{{ Form::password('password_confirmation', array('class' => 'form-control')) }}
</div>
{{ Form::submit('Add', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
</div>
@endsection
The edit
view is a form that allows us to edit users
and their roles
. Using Laravel's form model binding the form is automatically populated with the previous values.
edit
视图是一种表格,允许我们编辑users
及其roles
。 使用Laravel的表单模型绑定,将使用先前的值自动填充表单。
{{-- \resources\views\users\edit.blade.php --}}
@extends('layouts.app')
@section('title', '| Edit User')
@section('content')<div class='col-lg-4 col-lg-offset-4'>
<h1><i class='fa fa-user-plus'></i> Edit {{$user->name}}</h1>
<hr>
{{ Form::model($user, array('route' => array('users.update', $user->id), 'method' => 'PUT')) }}{{-- Form model binding to automatically populate our fields with user data --}}
<div class="form-group">
{{ Form::label('name', 'Name') }}
{{ Form::text('name', null, array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('email', 'Email') }}
{{ Form::email('email', null, array('class' => 'form-control')) }}
</div>
<h5><b>Give Role</b></h5>
<div class='form-group'>
@foreach ($roles as $role)
{{ Form::checkbox('roles[]', $role->id, $user->roles ) }}
{{ Form::label($role->name, ucfirst($role->name)) }}<br>
@endforeach
</div>
<div class="form-group">
{{ Form::label('password', 'Password') }}<br>
{{ Form::password('password', array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('password', 'Confirm Password') }}<br>
{{ Form::password('password_confirmation', array('class' => 'form-control')) }}
</div>
{{ Form::submit('Add', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
</div>
@endsection
###Permission Controller
###权限控制器
Now let's tackle the PermissionController
Create the file and paste the following code:
现在让我们解决PermissionController
创建文件并粘贴以下代码:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
//Importing laravel-permission models
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Session;
class PermissionController extends Controller {
public function __construct() {
$this->middleware(['auth', 'isAdmin']); //isAdmin middleware lets only users with a //specific permission permission to access these resources
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index() {
$permissions = Permission::all(); //Get all permissions
return view('permissions.index')->with('permissions', $permissions);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create() {
$roles = Role::get(); //Get all roles
return view('permissions.create')->with('roles', $roles);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
$this->validate($request, [
'name'=>'required|max:40',
]);
$name = $request['name'];
$permission = new Permission();
$permission->name = $name;
$roles = $request['roles'];
$permission->save();
if (!empty($request['roles'])) { //If one or more role is selected
foreach ($roles as $role) {
$r = Role::where('id', '=', $role)->firstOrFail(); //Match input role to db record
$permission = Permission::where('name', '=', $name)->first(); //Match input //permission to db record
$r->givePermissionTo($permission);
}
}
return redirect()->route('permissions.index')
->with('flash_message',
'Permission'. $permission->name.' added!');
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id) {
return redirect('permissions');
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id) {
$permission = Permission::findOrFail($id);
return view('permissions.edit', compact('permission'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id) {
$permission = Permission::findOrFail($id);
$this->validate($request, [
'name'=>'required|max:40',
]);
$input = $request->all();
$permission->fill($input)->save();
return redirect()->route('permissions.index')
->with('flash_message',
'Permission'. $permission->name.' updated!');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id) {
$permission = Permission::findOrFail($id);
//Make it impossible to delete this specific permission
if ($permission->name == "Administer roles & permissions") {
return redirect()->route('permissions.index')
->with('flash_message',
'Cannot delete this Permission!');
}
$permission->delete();
return redirect()->route('permissions.index')
->with('flash_message',
'Permission deleted!');
}
}
In the store()
method, we are making it possible for a role
to be selected as a permission
is created. After validating and saving the permission
name field, a check is done if a role
was selected if it was, a permission
is assigned to the selected role
.
在store()
方法中,随着创建permission
,我们可以选择一个role
。 验证并保存permission
名称字段后,检查是否选择了一个role
,如果已选择,则将permission
分配给所选role
。
###Permission View
###权限视图
Three views are needed here as well. The index
view would list in a table all the available permissions, the create
view is a form which would be used to create a new permission
and the edit view is a form that let's us edit existing permission
.
这里也需要三个视图。 index
视图将在表中列出所有可用的权限, create
视图是用于创建新permission
的表单,而编辑视图是让我们编辑现有permission
的表单。
{{-- \resources\views\permissions\index.blade.php --}}
@extends('layouts.app')
@section('title', '| Permissions')
@section('content')<div class="col-lg-10 col-lg-offset-1">
<h1><i class="fa fa-key"></i>Available Permissions
<a href="{{ route('users.index') }}" class="btn btn-default pull-right">Users</a>
<a href="{{ route('roles.index') }}" class="btn btn-default pull-right">Roles</a></h1>
<hr>
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Permissions</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
@foreach ($permissions as $permission)
<tr>
<td>{{ $permission->name }}</td>
<td>
<a href="{{ URL::to('permissions/'.$permission->id.'/edit') }}" class="btn btn-info pull-left" style="margin-right: 3px;">Edit</a>
{!! Form::open(['method' => 'DELETE', 'route' => ['permissions.destroy', $permission->id] ]) !!}
{!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}
{!! Form::close() !!}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<a href="{{ URL::to('permissions/create') }}" class="btn btn-success">Add Permission</a>
</div>
@endsection
The following is the create
view
以下是create
视图
{{-- \resources\views\permissions\create.blade.php --}}
@extends('layouts.app')
@section('title', '| Create Permission')
@section('content')<div class='col-lg-4 col-lg-offset-4'>
<h1><i class='fa fa-key'></i> Add Permission</h1>
<br>
{{ Form::open(array('url' => 'permissions')) }}
<div class="form-group">
{{ Form::label('name', 'Name') }}
{{ Form::text('name', '', array('class' => 'form-control')) }}
</div><br>
@if(!$roles->isEmpty()) //If no roles exist yet
<h4>Assign Permission to Roles</h4>
@foreach ($roles as $role)
{{ Form::checkbox('roles[]', $role->id ) }}
{{ Form::label($role->name, ucfirst($role->name)) }}<br>
@endforeach
@endif
<br>
{{ Form::submit('Add', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
</div>
@endsection
And finally the edit
view:
最后是edit
视图:
@extends('layouts.app')
@section('title', '| Edit Permission')
@section('content')<div class='col-lg-4 col-lg-offset-4'>
<h1><i class='fa fa-key'></i> Edit {{$permission->name}}</h1>
<br>
{{ Form::model($permission, array('route' => array('permissions.update', $permission->id), 'method' => 'PUT')) }}{{-- Form model binding to automatically populate our fields with permission data --}}
<div class="form-group">
{{ Form::label('name', 'Permission Name') }}
{{ Form::text('name', null, array('class' => 'form-control')) }}
</div>
<br>
{{ Form::submit('Edit', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
</div>
@endsection
###Role Controller
角色控制器
The RoleController
is quite similar to the UserController
. This controller will allow us to create roles
and assign one or more permissions
to a role
. Create the file and paste the following code:
RoleController
与UserController
非常相似。 该控制器将允许我们创建roles
并为一个role
分配一个或多个permissions
。 创建文件并粘贴以下代码:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
//Importing laravel-permission models
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Session;
class RoleController extends Controller {
public function __construct() {
$this->middleware(['auth', 'isAdmin']);//isAdmin middleware lets only users with a //specific permission permission to access these resources
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index() {
$roles = Role::all();//Get all roles
return view('roles.index')->with('roles', $roles);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create() {
$permissions = Permission::all();//Get all permissions
return view('roles.create', ['permissions'=>$permissions]);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
//Validate name and permissions field
$this->validate($request, [
'name'=>'required|unique:roles|max:10',
'permissions' =>'required',
]
);
$name = $request['name'];
$role = new Role();
$role->name = $name;
$permissions = $request['permissions'];
$role->save();
//Looping thru selected permissions
foreach ($permissions as $permission) {
$p = Permission::where('id', '=', $permission)->firstOrFail();
//Fetch the newly created role and assign permission
$role = Role::where('name', '=', $name)->first();
$role->givePermissionTo($p);
}
return redirect()->route('roles.index')
->with('flash_message',
'Role'. $role->name.' added!');
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id) {
return redirect('roles');
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id) {
$role = Role::findOrFail($id);
$permissions = Permission::all();
return view('roles.edit', compact('role', 'permissions'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id) {
$role = Role::findOrFail($id);//Get role with the given id
//Validate name and permission fields
$this->validate($request, [
'name'=>'required|max:10|unique:roles,name,'.$id,
'permissions' =>'required',
]);
$input = $request->except(['permissions']);
$permissions = $request['permissions'];
$role->fill($input)->save();
$p_all = Permission::all();//Get all permissions
foreach ($p_all as $p) {
$role->revokePermissionTo($p); //Remove all permissions associated with role
}
foreach ($permissions as $permission) {
$p = Permission::where('id', '=', $permission)->firstOrFail(); //Get corresponding form //permission in db
$role->givePermissionTo($p); //Assign permission to role
}
return redirect()->route('roles.index')
->with('flash_message',
'Role'. $role->name.' updated!');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$role = Role::findOrFail($id);
$role->delete();
return redirect()->route('roles.index')
->with('flash_message',
'Role deleted!');
}
}
###Roles View
###角色视图
Three views are needed here as well. The index
view to display available roles
and associated permissions
, the create
view to add a new role
and a view to edit an existing role
. Create the index.blade.php
file and paste the following:
这里也需要三个视图。 index
视图显示可用的roles
和关联的permissions
, create
视图添加新的role
以及编辑现有role
的视图。 创建index.blade.php
文件并粘贴以下内容:
{{-- \resources\views\roles\index.blade.php --}}
@extends('layouts.app')
@section('title', '| Roles')
@section('content')<div class="col-lg-10 col-lg-offset-1">
<h1><i class="fa fa-key"></i> Roles
<a href="{{ route('users.index') }}" class="btn btn-default pull-right">Users</a>
<a href="{{ route('permissions.index') }}" class="btn btn-default pull-right">Permissions</a></h1>
<hr>
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Role</th>
<th>Permissions</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
@foreach ($roles as $role)
<tr>
<td>{{ $role->name }}</td>
<td>{{ str_replace(array('[',']','"'),'', $role->permissions()->pluck('name')) }}</td>{{-- Retrieve array of permissions associated to a role and convert to string --}}
<td>
<a href="{{ URL::to('roles/'.$role->id.'/edit') }}" class="btn btn-info pull-left" style="margin-right: 3px;">Edit</a>
{!! Form::open(['method' => 'DELETE', 'route' => ['roles.destroy', $role->id] ]) !!}
{!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}
{!! Form::close() !!}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<a href="{{ URL::to('roles/create') }}" class="btn btn-success">Add Role</a>
</div>
@endsection
For the create
view:
对于create
视图:
@extends('layouts.app')
@section('title', '| Add Role')
@section('content')<div class='col-lg-4 col-lg-offset-4'>
<h1><i class='fa fa-key'></i> Add Role</h1>
<hr>
{{ Form::open(array('url' => 'roles')) }}
<div class="form-group">
{{ Form::label('name', 'Name') }}
{{ Form::text('name', null, array('class' => 'form-control')) }}
</div>
<h5><b>Assign Permissions</b></h5>
<div class='form-group'>
@foreach ($permissions as $permission)
{{ Form::checkbox('permissions[]', $permission->id ) }}
{{ Form::label($permission->name, ucfirst($permission->name)) }}<br>
@endforeach
</div>
{{ Form::submit('Add', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
</div>
@endsection
And for the edit
view:
对于edit
视图:
@extends('layouts.app')
@section('title', '| Edit Role')
@section('content')<div class='col-lg-4 col-lg-offset-4'>
<h1><i class='fa fa-key'></i> Edit Role: {{$role->name}}</h1>
<hr>
{{ Form::model($role, array('route' => array('roles.update', $role->id), 'method' => 'PUT')) }}
<div class="form-group">
{{ Form::label('name', 'Role Name') }}
{{ Form::text('name', null, array('class' => 'form-control')) }}
</div>
<h5><b>Assign Permissions</b></h5>
@foreach ($permissions as $permission)
{{Form::checkbox('permissions[]', $permission->id, $role->permissions ) }}
{{Form::label($permission->name, ucfirst($permission->name)) }}<br>
@endforeach
<br>
{{ Form::submit('Edit', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
</div>
@endsection
###Middleware
###中间件
To restrict access to the roles
and permissions
page, a middleware was included called isAdmin
in our PermissionController
and RoleController
. This middleware counts how many users are in the Users table, and if there are more than one users, it checks if the current authenticated User has the permission to 'Administer roles & permissions'. To create a permission visit http://localhost:8000/permissions/create
. Then go to http://localhost:8000/roles/create
to create a role
, to which you can now assign the permission
you created. For example you can create a permission called 'Administer roles & permissions' and a 'Admin' role
to which you would assign this permission
. Create the AdminMiddleware
in the directory app/Http/Middleware/
and enter the following code:
为了限制对roles
和permissions
页面的访问,在PermissionController
和RoleController
包含了一个名为isAdmin
的中间件。 该中间件计算“用户”表中有多少用户,如果有多个用户,它将检查当前经过身份验证的用户是否具有“管理角色和权限”的权限。 要创建权限,请访问http://localhost:8000/permissions/create
。 然后转到http://localhost:8000/roles/create
创建一个role
,您现在可以为其分配创建的permission
。 例如,您可以创建一个名为“管理角色和权限”的权限以及一个向其分配此permission
的“管理员” role
。 在app/Http/Middleware/
目录中创建AdminMiddleware
,然后输入以下代码:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use App\User;
class AdminMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$user = User::all()->count();
if (!($user == 1)) {
if (!Auth::user()->hasPermissionTo('Administer roles & permissions')) //If user does //not have this permission
{
abort('401');
}
}
return $next($request);
}
}
A middleware called clearance
was also included in our PostController
. This middleware would check if a user
has the permissions
Administer roles & permissions, Create Post, Edit Post and Delete Post.
中间件称为clearance
也包括在我们的PostController
。 如果这个中间件将检查user
有permissions
辖角色和权限,建立邮政,编辑帖子和删除帖子。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class ClearanceMiddleware {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next) {
if (Auth::user()->hasPermissionTo('Administer roles & permissions')) //If user has this //permission
{
return $next($request);
}
if ($request->is('posts/create'))//If user is creating a post
{
if (!Auth::user()->hasPermissionTo('Create Post'))
{
abort('401');
}
else {
return $next($request);
}
}
if ($request->is('posts/*/edit')) //If user is editing a post
{
if (!Auth::user()->hasPermissionTo('Edit Post')) {
abort('401');
} else {
return $next($request);
}
}
if ($request->isMethod('Delete')) //If user is deleting a post
{
if (!Auth::user()->hasPermissionTo('Delete Post')) {
abort('401');
}
else
{
return $next($request);
}
}
return $next($request);
}
}
Add AdminMiddleware::class
and ClearanceMiddleware::class
to the $routeMiddleware
property of /app/Http/kernel.php
like this:
添加AdminMiddleware::class
和ClearanceMiddleware::class
为$routeMiddleware
财产/app/Http/kernel.php
是这样的:
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'isAdmin' => \App\Http\Middleware\AdminMiddleware::class,
'clearance' => \App\Http\Middleware\ClearanceMiddleware::class,
];
In both middelwares a 401 exception would be thrown if the conditions are not meet. Let's create a custom 401 error page:
如果不满足条件,则在这两种中间件中都将抛出401异常。 让我们创建一个自定义401错误页面:
{{-- \resources\views\errors\401.blade.php --}}
@extends('layouts.app')
@section('content')<div class='col-lg-4 col-lg-offset-4'>
<h1><center>401<br>
ACCESS DENIED</center></h1>
</div>
@endsection
###Wrapping Up
###结语
First lets create an 'Admin' user and then create the necessary permissions and roles. Click on Register and create a user, then go to http://localhost:8000/permissions
and create permissions to Create Post
, Edit Post
, Delete Post
and Administer roles & permissions
. After creating these permissions, your permissions page should look like this:
首先让我们创建一个“管理员”用户,然后创建必要的权限和角色。 单击注册并创建用户,然后转到http://localhost:8000/permissions
并创建Create Post
, Edit Post
, Delete Post
以及Administer roles & permissions
。 创建这些权限后,您的权限页面应如下所示:
Next, you need to create roles
to which you would add the Create, Edit and Delete Permissions. Click on Roles and create these roles
:
接下来,您需要创建要向其添加创建,编辑和删除权限的roles
。 单击角色并创建以下roles
:
- Admin- A user assigned to this role would have all permissions 管理员-分配给该角色的用户将拥有所有权限
- Owner- A user assigned to this role would have selected permissions assigned to it by Admin 所有者-分配给该角色的用户将选择管理员分配给它的权限
Finally assign the Role of 'Admin' to the currently logged in User. Click on Users and then Edit. Check the Admin box under Give Role:
最后,将“管理员”角色分配给当前登录的用户。 单击用户,然后编辑。 选中“授予角色”下的“管理员”框:
After assigning the 'Admin' role
to our user
, notice that you now have a new Admin link in the drop of the navigation, this links to our users page. Now create a new user
and give it the more restrictive role
of Owner. If you login as this user and try to visit the User, Role or Permission pages you get this as expected:
在为我们的user
分配了“管理员” role
后,请注意,您现在在导航的下拉菜单中有了一个新的管理员链接,该链接指向我们的用户页面。 现在创建一个新user
并赋予它所有者更多的限制role
。 如果您以该用户身份登录并尝试访问“用户”,“角色”或“权限”页面,则会按预期获得此信息:
The Owner role
does not have permission to Administer Roles & Users
hence the exception is thrown.
所有者role
无权Administer Roles & Users
因此将引发异常。
To demonstrate how this works for posts
, create a post
by clicking on New Article. After creating the post, view the post
and you would notice you have along with the Back button, an Edit and Delete button as shown below:
要演示此方法对posts
工作原理,请单击“新建文章”以创建post
。 创建帖子后,查看该post
,您会注意到您拥有“返回”按钮,“编辑和删除”按钮,如下所示:
Now if you logout and view the post only the Back button will be available to us. This also works if you have a logged in user who does not have permissions to Edit or Delete Post.
现在,如果您注销并查看帖子,则只有“返回”按钮可供我们使用。 如果您具有没有编辑或删除帖子权限的登录用户,这也可以使用。
###Conclusion
###结论
The laravel-permission package makes it relatively easy to build a role and permission system. To recap we have considered installation of the laravel-permission package, laravel-permission blade directives, creating a custom middleware and implementing an access control list in a Laravel application. You can look at the final product on Github and if you have any questions or comments, don’t hesitate to post them below.
laravel-permission包使构建角色和权限系统相对容易。 概括地说,我们考虑过安装laravel-permission软件包,laravel-permission刀片指令,创建自定义中间件并在Laravel应用程序中实现访问控制列表。 您可以在Github上查看最终产品,如果有任何疑问或意见,请随时在下面发布。
翻译自: https://scotch.io/tutorials/user-authorization-in-laravel-54-with-spatie-laravel-permission