John Davidson

php - Laravel resource routes with id's in the URL and model association

0 comments
Message:


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



  • offer (List)

  • offer/10 (Show)

  • offer/10/edit (Edit)

  • offer/create (Create)

  • offer/10/update (Saving edit)

  • offer/10/store (Saving create)

  • offer/10/delete (Destroy offer)


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:



  • 25/offer (List)

  • 25/offer/10 (Show)

  • 25/offer/10/edit (Edit)

  • 25/offer/create (Create)

  • 25/offer/10/update (Saving edit)

  • 25/offer/10/store (Saving create)

  • 25/offer/10/delete (Destroy offer)


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}



My Answer:
In Laravel, resource routes are used to define routes for CRUD operations on a resource, such as a model. To define resource routes with an id parameter, you can use the following code in your routes/web.php file:

php
use App\Http\Controllers\ResourceController;

Route::resource('resources', ResourceController::class);

// Define custom route with id parameter
Route::get('resources/{id}/custom', [ResourceController::class, 'customMethod']);


In the above code, we are defining a resource route for the 'resources' resource using the ResourceController class. This will automatically generate routes for all CRUD operations on the 'resources' resource, including routes with an id parameter.

Additionally, we are defining a custom route with the path 'resources/{id}/custom' that will be handled by the 'customMethod' method in the ResourceController class. This route will have an id parameter that can be accessed in the controller method.

Make sure to replace 'ResourceController' with the actual name of your controller class and 'customMethod' with the name of the method that will handle the custom route logic.

Rate this post

3 of 5 based on 6757 votes

Comments




© 2024 Hayatsk.info - Personal Blogs Platform. All Rights Reserved.
Create blog  |  Privacy Policy  |  Terms & Conditions  |  Contact Us