路由模型为租户前缀Route::resource()绑定多个参数

Posted

技术标签:

【中文标题】路由模型为租户前缀Route::resource()绑定多个参数【英文标题】:Route Model Binding multiple parameters for tenant prefix Route::resource() 【发布时间】:2017-09-11 23:01:53 【问题描述】:

我正在使用 Laravel 的 Resource Controllers 功能开发 API,并将 Orchestral Multi-tenant Database Schema Manager 用作单一数据库

在我的控制方法中,我使用 Route Model Binding 将模型 ID 注入到路由或控制器操作中,经常查询以检索与该 ID 对应的模型。

我的 API 中的一些相关路由

| POST      | api/v1/tenant/fornecedores                     | store  | App\Http\Controllers\Api\Fornecedor\FornecedorController@store  | api,tenant,jwt.auth |
| GET|HEAD  | api/v1/tenant/fornecedores                     | index  | App\Http\Controllers\Api\Fornecedor\FornecedorController@index  | api,tenant,jwt.auth |
| GET|HEAD  | api/v1/tenant/fornecedores/count               |        | App\Http\Controllers\Api\Fornecedor\FornecedorController@count  | api,tenant,jwt.auth |
| PUT|PATCH | api/v1/tenant/fornecedores/fornecedor        | update | App\Http\Controllers\Api\Fornecedor\FornecedorController@update | api,tenant,jwt.auth |
| GET|HEAD  | api/v1/tenant/fornecedores/fornecedor        | show   | App\Http\Controllers\Api\Fornecedor\FornecedorController@show   | api,tenant,jwt.auth |
| GET|HEAD  | api/v1/tenant/fornecedores/fornecedor/audits |        | App\Http\Controllers\Api\Fornecedor\FornecedorController@audits | api,tenant,jwt.auth |
...

我的 API 路由文件示例:

// API V1
Route::group(['prefix' => 'v1/tenant', 'middleware' => 'tenant'], function () 

    // Fornecedores
    Route::group(['prefix' => 'fornecedores'], function () 
        Route::get('count', 'Api\Fornecedor\FornecedorController@count');
        Route::get('fornecedor/audits', 'Api\Fornecedor\FornecedorController@audits');

        Route::resource('/', 'Api\Fornecedor\FornecedorController', [
            'parameters' => ['' => 'fornecedor'],
            'except' => ['create', 'edit', 'destroy']
        ]);
    );
);

这些是我的FornecedorController.php的一些方法:

public function index()

    return $this->fornecedorService->getFornecedoresPaginate();


// This is line 48 (throw below):
public function show(Fornecedor $fornecedor)

    return $fornecedor;

但是,当尝试访问使用路由模型绑定的 URL 时,我收到以下错误:

网址: /api/v1/1/fornecedores/1

FatalThrowableError in FornecedorController.php line 48:
Type error: Argument 1 passed to App\Http\Controllers\Api\Fornecedor\FornecedorController::show() must be an instance of App\Models\Fornecedor, string given

这是所有的痕迹:

in FornecedorController.php line 48
at FornecedorController->show('1', object(Fornecedor))
at call_user_func_array(array(object(FornecedorController), 'show'), array('tenant' => '1', 'fornecedor' => object(Fornecedor))) in  Controller.php line 55
at Controller->callAction('show', array('tenant' => '1', 'fornecedor' => object(Fornecedor))) in ControllerDispatcher.php line 44
at ControllerDispatcher->dispatch(object(Route), object(FornecedorController), 'show') in Route.php line 203
at Route->runController() in Route.php line 160
at Route->run() in Router.php line 559
at Router->Illuminate\Routing\closure(object(Request)) in Pipeline.php line 30
at Pipeline->Illuminate\Routing\closure(object(Request)) in GetUserFromToken.php line 46
at GetUserFromToken->handle(object(Request), object(Closure)) in
...

我可以验证在检索参数时显然存在混淆。检查路由参数时,结果如下:

public function show($fornecedor)

    dd(\Route::current()->parameters());

网址:/api/v1/1/fornecedores/18

结果:

array:2 [
  "tenant" => "1"
  "fornecedor" => "18"
]

当尝试检索提供者的路由时:

public function show($fornecedor)

    dd($fornecedor);

网址:/api/v1/1/fornecedores/18

结果:

"1"

即使使用绑定我得到的参数也不正确。并且其他不使用第二个参数的路由都可以。

谁能告诉我更好的方法?

谢谢!

【问题讨论】:

【参考方案1】:

第一个猜测是你试图隐式绑定 fornecedor 参数,而 Laravel 无法解析或识别它。

您可以在路由文件(routes/web.phproutes.php)的下方某处声明参数-模型关系

Route::model('fornecedor', \App\Models\ Fornecedor::class);

您的show 方法也不适合tenent 参数。该方法应如下所示:

public function show($tenant, Fornecedor $fornecedor)
    return $fornecedor;

public function show(Tenant $tenant, Fornecedor $fornecedor)
    return $fornecedor;

【讨论】:

以上是关于路由模型为租户前缀Route::resource()绑定多个参数的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 资源路由命名前缀

组前缀内的路由名称不包括前缀

Laravel 5中带有前缀的路由组中的路由资源

带有前缀和资源的laravel嵌套路由不起作用

LARAVEL - 使用 Route::resource 生成路由时无法使用销毁路由

Laravel 5.2 使用 uuid 字符串作为 id 的隐式路由模型绑定