如何(正确)使用具有依赖关系的表单请求 + 策略 + 资源路由?

Posted

技术标签:

【中文标题】如何(正确)使用具有依赖关系的表单请求 + 策略 + 资源路由?【英文标题】:How to (properly) use form requests + policies + resource routes with dependencies? 【发布时间】:2018-04-22 08:51:56 【问题描述】:

我的用例是用户是/拥有一家拥有员工的公司。

使用表单控制器和模型策略我试图找出最好/正确的方法应该是什么。

路线:

    Route::resource('company', \App\Http\Controllers\Api\v1\CompanyController::class);
    Route::resource('employee', \App\Http\Controllers\Api\v1\EmployeeController::class);

员工商店要求:

namespace App\Http\Requests;

use App\Models\Employee;
use Illuminate\Foundation\Http\FormRequest;

class EmployeeStoreRequest extends FormRequest

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    
        return $this->user()->can('create', Employee::class);
    

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    
        return [
            'company_id' => 'required|integer|exists:companies,id'
        ];
    

员工政策:

...
/**
 * Determine whether the user can create employees.
 *
 * @param  \App\User $user
 * @return mixed
 */
public function create(User $user)

    return $user->can('update', Company::find(
        app('request')->get('company_id')
    ));

...

因此,我对策略如何检查用户是否可以编辑员工所属的公司并不特别满意,因为这只发生在 http 上,对于控制台/测试,这会中断。

那么添加这个检查最合乎逻辑的方法是在表单请求的 authorize() 函数中,但是你正在检查策略之外的权限,这听起来不合逻辑。

简而言之,问题是:您如何以及为什么要使用表单请求和模型策略来做到这一点?

【问题讨论】:

【参考方案1】:

只需要在EmployeePolicy@create方法中添加公司的id,就可以在http之外使用了

EmployeePolicy

public function create(User $user, $companyId)

    return $user->can('update', $companyId);

EmployeeStoreRequest

public function authorize()

    return $this->user()->can('create', Employee::class, $this->request->get('company_id'));

您可以在 http 之外使用 tinker 对其进行测试

php artisan tinker
$user = User::find(2); // or whatever user you want to test with
$user->can('create', Employee::class, 3); // 3 = company_id

【讨论】:

你确定这条线是正确的吗? return $user->can('update', $companyId);。就像在这种情况下 Laravel 应该如何知道检查 CompanyPolicy 一样?我觉得return $user->can('update', Company::class, $companyId); 更合适,就像你在EmployeStoreRequest 中所做的那样

以上是关于如何(正确)使用具有依赖关系的表单请求 + 策略 + 资源路由?的主要内容,如果未能解决你的问题,请参考以下文章

具有依赖关系的 Android 库无法正确解析

继承具有“依赖关系”的 CustomViewController 的正确方法

如何发布具有多部分/表单数据编码的数组?

具有依赖关系的多个调用 redux-thunk

如何正确发布到双向关系

在纱线工作区中,如何强制解决子项目的依赖关系?