我的理解是,使用策略定义的能力确实是多态的,这意味着:
Gate::allows('update', $post);
Gate::allows('update', $comment);
如果两个对象属于不同的类,则调用使用不同策略注册的不同函数:
protected $policies = [
Post::class => PostPolicy::class,
Comment::class => CommentPolicy::class,
];
虽然在我看来,使用
$gate->define()
定义的能力不是多态的,这意味着使用相同策略名称的两个调用将相互覆盖:$gate->define('update', function ($user, $post) { /* THIS IS THROWN AWAY! */ });
$gate->define('update', function ($user, $comment) { /* the last one is kept */ });
这是对的吗?
文档中显示的非多态示例(
update-post
,update-comment
)的能力名称与策略示例(update
)中显示的能力名称之间是否存在任何关系?我的意思是,后缀
-post
是由laravel添加的还是推断的?还是只是一个例子? 最佳答案
策略定义能力和门定义能力之间存在显著差异。
当你使用门的define
方法时,你的能力名称将是added to the abilities array of the gate,数组键是能力名称。如果用相同的名称定义另一个能力(例如update
),它将覆盖旧的能力,因为不能有两个同名的数组键。因此在这种情况下,define($ability, $callback)
中的唯一标识符是能力。
相反,定义策略类时,能力名称是策略的实际方法名称。因此,可以有多个具有相同方法的类(例如update
),因为在本例中,唯一标识符是与第一个参数一起传递的类,所以Post::class
。
在授权检查期间的某个时刻,gate类检查if there's a policy associated with the first argument passed并基于该评估调用策略方法或已定义的能力回调。
因此,在使用define
时,不能有两个同名的能力,因为不可能:
$abilities = [
'update' => $callback1,
'update' => $callback2, // this will override the first
]
正如使用
$policies
时,不能将多个策略关联到一个类:$policies = [
Post::class => PostPolicy::class,
Post::class => AnotherPostPolicy::class, // this will override the first one
];
因此,如果您想使用
update
作为多个模型的能力名称,只需使用策略。这也应该回答最后一个问题:laravel不推断或添加任何内容,能力名称要么是传递给
define
的字符串,要么是在策略类上定义的方法名称。