我的理解是,使用策略定义的能力确实是多态的,这意味着:

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-postupdate-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的字符串,要么是在策略类上定义的方法名称。

10-06 04:06