Reputation: 2375
I have a laravel app with a bunch of CRUDS that has LIST, VIEW, EDIT, CREATE and DELETE. It's all working great. The problem I have thought is that one of those CRUDS will be filtered based on the company ID a user owns. The setup is that 1 user can own many companies and every company can have many offers. So the offer CRUD needs to be filtered based on the company id.
Before my changes the route looked like this
Route::resource('offers', 'OfferController');
So that ressource route takes care of generating the diffrent URLS
The resource seems to magically relate the offer ID with the model even if the ID is not specified in the route. And that's awesome. But it does not work anymore as soon as you add a new var in the URL.
My route now looks like this
Route::resource('{merch}/offers', 'OfferController');
Because there's a second ID involved the offer model can no longer "Auto relate"
After adding {merch} in the ressource I end up with a URL that looks like this:
Where 25 is the company ID and 10 is the offer ID
The controller before the add of the {merch} var in the URL looked like this
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'));
}
So I changed that to:
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'));
}
The problem I have is that $offer seems undefined now. It does not seem to find the actual offer ID anymore and can't seem to relate anything. The error I get talks about categories is not an instance of the collection $offer.
Note that before adding {merch} it was all working great. How can I benefit from the Laravel "magic" association when the URL has 2 ids?
When I saw that Offer $offer no longer relates I thought I might need to replace the route with something more specific. So I eded up doing something like this:
// 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');
But still, Offer $offer does not relate to the {id}
Upvotes: 2
Views: 1334
Reputation: 2375
Ok so after reading the laravel documentation theres a way called nested ressources to do exacly waht i needed. It goes like this:
Since the {merch} var i was looking for was the merchant ID, Theres a way to use resource to nest both of them in one call like this:
Route::resource('merchants.offers', 'OfferController');
The URL would then be
The controller would then look like this
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'));
}
And just like that everything was solved and worked as expected!
Upvotes: 1