Laravel Policy的authorize方法传参异常问题排查
问题涉及代码
控制器方法:
public function store(StoreTradeRequest $request, StoreTradeService $service) { $this->authorize('store', [Trade::class, $request->all()]); // ... }
授权策略(Policy)代码:
public function store(User $user, array $request): Response|bool { return $user->id == $request['trader_id']; }
当前代码可正常运行,但存在疑问:控制器中authorize方法的第二个参数目前传入的是包含Trade::class与请求数据的两项数组,可Policy方法实际仅需要用到请求数据。尝试移除Trade::class仅传入请求相关数据时,会抛出如下报错:
Too few arguments, 1 passed, 2 expected.
已尝试所有能想到的$request传参格式,运行结果均相同,尝试过的传参形式如下:
'store', $request 'store', [$request] 'store', $request->all() 'store', $request->validated() 'store', [$request->all()] 'store', [$request->validated()]
问题原因
这是Laravel框架授权机制的固定解析规则导致的,属于框架设计约定,不是代码bug。
- 当调用
authorize()方法走Policy授权时,如果是执行不需要依赖已有模型实例的操作(比如新建交易记录的store动作,不需要提前查询出Trade模型实例),必须传入对应模型的类名,框架完全靠这个类名定位到对应的Policy类,这个类名本身不会作为参数传递到Policy方法内部。 - Laravel解析
authorize()参数的固定逻辑:先从第二个参数(支持数组传多参)里找到第一个是模型类名/模型实例的元素,用它匹配绑定的Policy;数组里剩下的其他元素,才会按顺序拼接到当前登录用户参数之后,传给Policy的对应方法。
移除Trade::class后报错的原因
当不传Trade::class时,框架找不到用来定位Policy的模型标识,会走入无模型的授权解析逻辑:
- 框架默认会给所有授权回调/方法传入当前登录用户实例,作为第一个参数
- 没有模型标识的情况下,框架不会把传入的请求数据识别为需要透传给Policy的自定义参数,最终只给Policy方法传入了当前用户这1个参数
- 对应的Policy
store方法要求接收2个参数($user和$request数组),参数数量不匹配,就会抛出参数数量不足的错误。
其他传参格式测试无效的原因
所有不带Trade::class的传参写法,都因为参数列表里没有模型类名/模型实例作为Policy定位标识,都会触发上述参数解析错误,和传请求数据的格式没有任何关系。
说明:代码里传入的
Trade::class不是冗余参数,它是框架定位Policy的必要标识,哪怕Policy方法里完全用不到Trade模型的逻辑,只要是通过模型绑定的Policy做创建类资源的授权,就必须传入这个类名。
内容的提问来源于stack exchange,提问作者Bulent
相关产品推荐
相关产品推荐

