Laravel ACL 权限
打赏作者

layne

视频做得很好,支持!!

alias

最好有视频配套代码的源码…
否则看完回头研究的时候白瞎。

JellyBool

我的初衷一部分只是想让你们跟着视频写代码而已,只看不写永远学不会。 @alias

高永立 回复 JellyBool

代码不自己写,看是看不会的。支持站长。。

alias

@JellyBool 照着做打字员其实没啥用,关键是自己 做项目的时候能回头查,用个两三次才算掌握。我在重新看basic…上次是照着敲代码的,但是回头自己做的时候发现当时很多命令记不得了,laravel的零散知识点其实不少,你的很多小经验在手册上是查不来的,尤其喜欢。这次得好好做笔记了。做笔记和敲代码比较纠结…最好做了笔记,回头对着源码看。所以其实我更喜欢你的文章…不过看的出你视频好用心的,现在开始每课总结知识点了,basic的时候前半段就没有。建议而已,求全责备了。能有这么好的资料相当不错了。

JellyBool

好了,你看看 ? 如果你觉得视频不错的话 ,可以看看这里,我觉得vip套餐比较合算

https://laravist.com/vip @turnerhesz

ouuyo

thank you @JellyBool ,不过讲的好快

Addison

5.3AuthServiceProvider下的boot()与视频不一致,请教实现

JellyBool 回复 Addison

首先试试这个:

1.use Gate :

use Illuminate\Contracts\Auth\Access\Gate as GateContract;

2.改一下 boot 方法试试:

    public function boot(GateContract $gate)
    {
        $this->registerPolicies();
        //你的代码
    }
Addison 回复 JellyBool

谢谢回复。按你的回复测试通过。
不过在PostsController里用采用如下示例代码。

<?php
namespace App\Http\Controllers;
use Illuminate\Contracts\Auth\Access\Gate;
use Illuminate\Http\Request;
use App\Http\Requests;

class PostsController extends Controller
{
    public function show($id)
    {
        $post = \App\Post::findOrFail($id);
        \Auth::loginUsingId(1);
        $this->authorize('show-post', $post);
//        if(Gate::denies('show-post',$post))
//        {
//            abort(403,'Sorry');
//        }
        return $post->title;
    }
}

如果采用注释里的代码的话,会报如下错误:
FatalThrowableError in PostsController.php line 18:
Non-static method Illuminate\Contracts\Auth\Access\Gate::denies() cannot be called statically
(看了下Gate类,denies()方法不是静态方法。)

JellyBool 回复 Addison

应该就是 Gate 没用对吧。

use Gate;
sgemty

我想问$user->owns()这个方法是什么时候定义的?为什么我写就没有定义?

JellyBool 回复 sgemty

视频 6:33 秒看看,是这个么

Kwong Yan Chan

01:Laravel ACL 权限

  • 生成表:php artisan make:migration create_posts_table --create=posts
  • 创建字段
public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('user_id')->unsigned();
        $table->string('title');
        $table->text('body');
        $table->timestamps();
        $table->foreign('user_id')
              ->references('id')
              ->on('users')
              ->onDelete('cascade');

    });
}
  • 生成数据表php artisan migrate
  • 建立模型文件postsphp artisan make:model Post
  • 定义测试数据,并生成
$factory->define(App\Post::class, function (Faker\Generator $faker) {
    return [
        'user_id' => factory(\App\User::class)->create()->id,
        'title' => $faker->sentence,
        'body' => $faker->paragraph,
    ];
});
  • 生成控制器php artisan make:controller PostsController
  • show方法测试代码
public function show($id)
{
    $post = Post::findOrFail($id);

    return $post->title;
}
  • 注册路由Route::resource( 'posts','PostsController' );

  • 测试访问:OK

  • 找到Providers\AuthServiceProvider

  • 找到boot方法

public function boot(GateContract $gate)
{
    $this->registerPolicies($gate);

    ##判断这篇文章是否当前用户创建
    $gate->define( 'show-post',function( $user,$post ) {
        return $user->id == $post->user_id;
    });

}
  • 找到控制器show方法【跟视频的版本有出入,到此步出错,mark,我用的是:Laravel Framework version 5.1.45 (LTS)】,修改如下,修改后第一种方案后,效果同视频一致,第二种方案是正常的
use Illuminate\Contracts\Auth\Access\Gate as GateContract;//引用
class PostsController extends Controller
{
    protected $authCheck;//增加
    
    //增加
    public function __construct( GateContract $gate )
    {
        $this->authCheck = $gate;
    }
    
    public function show($id)
    {
        $post = Post::findOrFail($id);
        \Auth::loginUsingId(2);
        //$this->authorize( 'show-post',$post );#第二种方式
        if( !$this->authCheck->check( 'show-post',$post ) ) {
            abort( 403,'Sorry' );
        }

        return $post->title;
    }
  • 优化boot方法
public function boot(GateContract $gate)
{
    $this->registerPolicies($gate);

    ##判断这篇文章是否当前用户创建
    $gate->define( 'show-post',function( $user,$post ) {
        return $user->owns( $post );
    });

}
  • user模型增加owns方法
public function owns($post)
{
    return $this->id == $post->user_id;
}
  • 测试效果:ok

  • 使用@can @endcan 标签 进行权限控制

    • 视频中说是5.1之后增加了此标签
    • 我这个版本是5.1.45;可以使用此标签,
    • Ps:开始以为是 5.2才会有此标签,嗯,效果就如视频中一样
MarksGui888 回复 Kwong Yan Chan

感谢!代码比较完整,看了视频后整理看一遍收货比较大

Kwong Yan Chan 回复 MarksGui888

不客气 。加油一起上路吧

liwei19911991

你好 我想问一下这个$this->roles 是什么意思呢,我看模型只定义了roles()方法啊,谢谢!

JellyBool 回复 liwei19911991

你可以把它想象成执行 $this->roles() ,只不过 $this->roles 的话,laravel 就可以帮你取到关联的值了

liwei19911991 回复 JellyBool

好的,谢谢。我知道了是这个意思,可是还是不太懂,我登陆后在模型里面直接输出$this->roles为什么个空Collection,那不到值,然后在你这个地方能够取到值呢

JellyBool 回复 liwei19911991

在模型里面直接输出$this->roles?具体的代码是什么?位于什么位置?你确定你的数据库有对应的 role 和 user 关联

cnsecer

5.4的boot那点要怎么写呢,五点四并没有$gate

JellyBool 回复 cnsecer

直接使用 Gate 试试:

 public function boot()
    {
        $this->registerPolicies();

        Gate:: // 你的代码
    }
Psychic_role

@jellybool 老师你好,我的laravel是5.4版本
postsphp artisan make:model Post这条语句生成的post.php是空表,$fillable=[],这样对吗?
然后在factory(‘App\Post’)->create();这条语句执行时出错
PHP error: Array to string conversion in K:\workspace\phpstudy\WWW\acl\vendor\laravel\framework\src\Illuminate\Database\MySqlConnection.php on line 80

JellyBool 回复 Psychic_role

post.php是空表?

这是个 model 文件,跟空表没有什么关系吧。

$fillable=[],这样对吗?

这是设置 posts 这张表的可以直接填充的字段。

factory(‘App\Post’)->create();这条语句执行时出错

这个应该是单词写错了,单复数的问题

Psychic_role 回复 JellyBool

我看老师的视频里,model文件和controller文件里都有建立的空白方法啊,比如controller文件里的show\create\store方法,而我在cmd里make:controller create创建的控制器里是空白的,这是设置了哪个部分达到的呢?

JellyBool 回复 Psychic_role

php artisan make:controller PostController --resource

Psychic_role 回复 JellyBool

学到了,记笔记+。+

tzh 回复 Psychic_role

你好,请问 Array to string conversion这个错误是怎么解决的?

JellyBool 回复 tzh

这个我不知道,估计是数组和字符串搞混了

a359611223

5.4 支持 php artisan make:model Post -m 直接生成Post的migration表

a359611223

5.4中的写法应该是这样

    public function boot()
    {
        $this->registerPolicies();

        Gate::define('show-post',function($user,$post){
            return $user->id == $post->user_id;
        });
    }
}
flxxyz

laravel5.4的同学如果有问题可以看看这里,能不能解决你的问题

php artisan migrate

如果出现下面的错误,将 app/Providers/AppServiceProvider.php 里的boot方法加上 Schema::defauleStringLength(120), 这里(官方文档)1写的191对我没效果,如果你有效就先用把

Specified key was too long error

新建测试数据

php artisan tinker
factory('App\User')->create()  // 新建一个用户
factory('App\Post')->create()  // 这条创建文章可以多执行几次
exit  // 退出

新建模型

public function owns($post) {
    return $this->id == $post->user_id;
}

AuthServiceProvider.php

boot() 方法写入
this>registerPolicies();Gate::define(showpost,function(this->registerPolicies(); Gate::define('show-post',function(user,$post){
return user>owns(user->owns(post);
});


新建控制器

php artisan make:controller PostController -r    // 出现教主出现的效果

show() 方法里写

$post = Post::findOrFail($id);
Auth::loginUsingId(1);
return view('post.show', ['post' => $post]);

post目录下的视图文件show.blade.php

<h1>{ $post->title }</h1>
@can('show-post', $post)
    <a href="#">编辑文章</a>
@endcan

视图里写这些足够了
验证用户权限,就在控制器里的 Auth::loginUsingId(1) 修改值

当然如果还有错误的话,那应该是你没有用PHPstom的问题,引入类

taizujunshang

按着视频的方法,执行到这一步,浏览器打印结果报错,提示SQLSTATE[HY000] [2002] Connection refused,后来尝试将env文件的127.0.0.1改成 localhost, 问题就解决了,想问一下这是什么原因?我的开发环境就是用的 homestead.
public function show($id)
{
post=Post::findOrFail(post = Post::findOrFail(id);
return $post->title;
}