具有Spatie Laravel-Permission的Laravel 5.4中的用户授权

###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 ran

    migrations :跟踪已执行的迁移过程
  • users: This holds the users data of the application

    users :保存应用程序的用户数据
  • password_resets: Holds token information when users request a new password

    password_resets :在用户请求新密码时保存令牌信息
  • permissions: This holds the various permissions needed in the application

    permissions :拥有应用程序所需的各种权限
  • roles: This holds the roles in our application

    roles :这在我们的应用程序中拥有角色
  • role_has_permission: This is a pivot table that holds relationship information between the permissions table and the role table

    role_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 role

    givePermissionTo() :允许我们授予用户或角色权限
  • revokePermissionTo(): Revoke permission from a user or role

    revokePermissionTo() :撤消用户或角色的权限
  • hasPermissionTo(): Check if a user or role has a given permission

    hasPermissionTo() :检查用户或角色是否具有给定的权限
  • assignRole(): Assigns role to a user

    assignRole() :向用户分配角色
  • removeRole(): Removes role from a user

    removeRole() :从用户删除角色
  • hasRole(): Checks if a user has a role

    hasRole() :检查用户是否具有角色
  • hasAnyRole(Role::all()): Checks if a user has any of a given list of roles

    hasAnyRole(Role::all()) :检查用户是否具有给定的角色列表中的任何一个
  • hasAllRoles(Role::all()): Checks if a user has all of a given list of role

    hasAllRoles(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.

方法assignRolehasRolehasAnyRolehasAllRolesremoveRole可以接受字符串, Spatie\Permission\Models\Role-object\Illuminate\Support\Collection对象。 givePermissionTorevokePermissionTo方法可以接受字符串或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

此应用程序总共需要四个控制器。 让我们使用资源控制器,因为这会自动为我们添加存根方法。 我们的控制器将被称为

  1. PostController

    后控制器
  2. UserController

    用户控制器
  3. RoleController

    角色控制器
  4. 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.phpfile. 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.phpfile. Change the $redirectTo property to:

同样在RegisterController.php文件中。 将$redirectTo属性更改为:

protected $redirectTo = '/';

Do the same thing in the LoginController.phpfile.

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.phpin 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方法的访问限制为已认证的用户,另一个是尚未创建的自定义中间件。 这将负责我们的“权限和角色”系统。 接下来,将indexshow传递到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.

/路线是我们的主页的路线,这里更名为homeAuth ,当您运行生成路线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.phpfile 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.

这里需要三个视图: indexcreateedit视图。 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 PermissionControllerCreate 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:

RoleControllerUserController非常相似。 该控制器将允许我们创建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和关联的permissionscreate视图添加新的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:

为了限制对rolespermissions页面的访问,在PermissionControllerRoleController包含了一个名为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 。 如果这个中间件将检查userpermissions辖角色和权限,建立邮政,编辑帖子和删除帖子。

<?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::classClearanceMiddleware::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 PostEdit PostDelete 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

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值