Skip to content

Custom routes not being matched for (api-)resources #307

@patrickvuarnoz

Description

@patrickvuarnoz

Describe the bug

When you setup routes via resource() or apiResource() and add custom routes (for example a search route) like in the following example, then the search part of the request will be interpreted as the ID in a normal GET request.

app()->resource('/users', 'UsersController');
app()->get('/users/search', 'UsersController@search);

The problem lies in the router, i.e. in resource() and apiResource() where the routes are created with {id} in the paths:

static::match('DELETE', "$pattern/{id}", "$controller@destroy");
static::match('PUT|PATCH', "$pattern/{id}", "$controller@update");
...

For later route matching these {id} get translated into (.*?) which will simply match any route part that comes after the base path. E.g. for a request GET /users/search the part search will be interpreted as ID. As we are in resource territory we can assume that ids are numerical. So the parts in resource() and apiResource() with {id} should be changed to only match numerical ids. Something like:

static::match('DELETE', "$pattern/(\d+)", "$controller@destroy");
static::match('PUT|PATCH', "$pattern/(\d+)", "$controller@update");
...

Note: as a need-to-know workaround a route like /users/search can be registered before the resource. Like that it is being found first.

To Reproduce

Steps to reproduce the behavior:

  1. Create routes as demonstrated above

  2. Call GET /users/search

  3. Will most probably show some error about SQL

Expected behavior

Custom routes are matched no matter if they are registered before or after resource routes.

Additional context

Tested with Leaf 4.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions