首页 > 解决方案 > 在 URL 和模型关联中带有 id 的 Laravel 资源路由

问题描述

我有一个带有一堆 CRUDS 的 laravel 应用程序,其中包含 LIST、VIEW、EDIT、CREATE 和 DELETE。这一切都很好。我想到的问题是,其中一个 CRUDS 将根据用户拥有的公司 ID 进行过滤。设置是 1 个用户可以拥有许多公司,每个公司可以有许多报价。因此,offer CRUD 需要根据公司 id 进行过滤。

在我更改之前,路线看起来像这样

Route::resource('offers', 'OfferController');

因此 ressource 路由负责生成不同的 URL

即使在路由中未指定 ID,资源似乎也神奇地将商品 ID 与模型相关联。这太棒了。但是,一旦您在 URL 中添加新的 var,它就不再起作用了。

我的路线现在看起来像这样

Route::resource('{merch}/offers', 'OfferController');

由于涉及第二个 ID,报价模型不能再“自动关联”

在资源中添加 {merch} 后,我最终得到一个如下所示的 URL:

其中 25 是公司 ID,10 是报价 ID

在 URL 中添加 {merch} 变量之前的控制器如下所示

public function show(Offer $offer)
{
    abort_if(Gate::denies('offer_show'), Response::HTTP_FORBIDDEN, '403 Forbidden');

    $offer->load('categories', 'tags');

    return view('admin.offers.show', compact('offer'));
}

所以我将其更改为:

public function show($merch, Offer $offer)
{
    abort_if(Gate::denies('offer_show'), Response::HTTP_FORBIDDEN, '403 Forbidden');

    $offer->load('categories', 'tags');

    return view('admin.offers.show', compact('offer', 'merch'));
}

我遇到的问题是 $offer 现在似乎未定义。它似乎不再找到实际的报价 ID,并且似乎无法关联任何东西。我得到的关于类别的错误不是集合 $offer 的一个实例。

请注意,在添加 {merch} 之前,一切都很好。当 URL 有 2 个 id 时,我如何从 Laravel“魔术”关联中受益?

当我看到 Offer $offer 不再相关时,我想我可能需要用更具体的东西替换路线。所以我做了这样的事情:

// Offers
Route::get('{merch}/offers', 'OfferController@index');
Route::get('{merch}/offers/create', 'OfferController@create');
Route::post('{merch}/offers/store', 'OfferController@store');
Route::get('{merch}/offers/{id}/edit', 'OfferController@edit');
Route::put('{merch}/offers/{id}/update', 'OfferController@update');
Route::delete('{merch}/offers/{id}/delete', 'OfferController@destroy');
Route::get('{merch}/offers/{id}', 'OfferController@show');

但是,Offer $offer 与 {id} 无关

标签: phplaravel

解决方案


好的,所以在阅读了 laravel 文档之后,有一种称为嵌套资源的方法可以完全满足我的需要。它是这样的:

由于我正在寻找的 {merch} 变量是商家 ID,因此有一种方法可以使用资源将它们嵌套在一个调用中,如下所示:

Route::resource('merchants.offers', 'OfferController');

然后 URL 将是

  • 商家/25/优惠(列表)
  • 商家/25/优惠/10(显示)
  • 商家/25/优惠/10/编辑(编辑)
  • 商家/25/优惠/创建(创建)
  • 商家/25/offers/10/update(保存编辑)
  • 商家/25/offers/10/store(保存创建)
  • 商家/25/offers/10/delete(销毁offer)

然后控制器看起来像这样

public function show(Merchant $merchant, Offer $offer)
{
    abort_if(Gate::denies('offer_show'), Response::HTTP_FORBIDDEN, '403 Forbidden');
    $offer->load('categories', 'tags');
    return view('admin.offers.show', compact('offer', 'merchant'));
}

就像这样,一切都得到了解决并按预期工作!


推荐阅读