Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mehany's avatar
Level 13

LogicException in RouteCompiler

I have an app that has an admin panel. In the admin area Routes ( which has a prefix of /admin ) I have

    Route::resource('documents/{product?}', 'ManageDocumentsController'); 
    Route::resource('orders/{type?}', 'ManageOrdersController');

So I run this url in my browser ( example.com/admin/orders/download ), I get

Route pattern "/admin/documents/{product}/{{product}}" cannot reference variable name "product" more than once.

I run this url in my browser ( example.com/admin/documents/topo ) it renders the list.

If I switch the order or the route's declaration, it will do the same error. The one that comes after is the one that does not render :(

      Route::resource('orders/{type?}', 'ManageOrdersController');
      Route::resource('documents/{product?}', 'ManageDocumentsController'); 

     Route pattern "/admin/orders/{type}/{{type}}" cannot reference variable name "type" more than once.
0 likes
14 replies
mehany's avatar
Level 13

I think the reason is Route::resource('orders/{type?}' is the same as Route::resource('orders/{id?}' but I am not sure why one would work and the second don't!

SaeedPrez's avatar
Route::resource('orders', 'ManageOrdersController');
Route::resource('documents', 'ManageDocumentsController');

documentation

mehany's avatar
Level 13

ok @SaeedPrez, I wish to simply type resource and then it will work with a search parameter! but the router matches {type?} to {id?} so I would like to provide another parameter to list a sub type . To get a better idea here is the controller

public function index(Request $request, $product = null)
            $allPdfs = ($product != null) ?
            PdfDocument::where('pdf_type', '=', $product):
            PdfDocument::select('*');

        $pdfs =   Datatables::of($allPdfs)->make(true);


        if($request->wantsJson())
        {
            return $pdfs;
        }

        return view('admin.documents.index',
            ['page_title' => (($product != null) ?
                    $product : "" ). ' PDF documents List',
             'type'       => $product
            ]);
mehany's avatar
Level 13

It looks like that does not work with resource.

SaeedPrez's avatar

@mehany if resource routes isn't the best option for you then you don't have to use them. Just write out each of your routes and you get a lot more control.

Even if you care anything about good/best practice, writing all routes is much better than using the resource option.

mehany's avatar
Level 13

Well i need crud so that is why I am using resource . Any ways, it looks like it is what it is, I just wish if i can pass to resource more actions. Not sure if this is possible. here is how I solved it earlier

Route::get('documents/list/{product?}', 'ManageDocumentsController@index');
Route::resource('documents', 'ManageDocumentsController');

If you ever use Datatables.js along with complex data, you will run into this.

Can you reduce my code one more line? :)

SaeedPrez's avatar

Well i need crud so that is why I am using resource

I don't understand.. What does that have to do with anything? Route::resource() is simply a helper method, you can write out all the routes yourself without it and that way have more control and format them exactly after your needs.

It looks like you're creating a problem that doesn't need to exist. There's really no actual problem to solve here.

So I wish you the best with your project.

mehany's avatar
Level 13

Ok thank you! but after that I looked into this, the problem is really making an option available to hook in the same resource name additional methods/actions when needed! Why? because I think that is an elegant syntax! something as the one you suggested Regular Expression Constraints would work as well.

I understand a crud resource is just intended for crud operations but I want to use the same resource name in the url for the index method to show other lists of the same resource. Hope this gives you better understanding @SaeedPrez of what I was after. Don't you people think this would be a cool feature?

SaeedPrez's avatar

@mehany

You can add more custom routes with route filter like shown below.. but you have to be very careful and make sure they don't step over each other.

// Example
Route::get('orders/{type}', 'ManageOrdersController@showType')
    ->where('type', '[A-Za-z]{5}')
    ->name('orders.type');

Route::resource('orders', 'ManageOrdersController');
mehany's avatar
Level 13

When i try the code you provided, the router dispatches the action the ::show() method.

SaeedPrez's avatar

What does your type data look like? Is it an integer or string, how long, etc?

SaeedPrez's avatar

Like I mentioned earlier, you need to make sure they don't step over each other. So you need to create a couple of global route filters, one for id to make sure it only contains digits and also one for type.

All information you need can be found here

Please or to participate in this conversation.