Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom key support for implicit enum route binding #41776

Closed
wants to merge 2 commits into from
Closed

Custom key support for implicit enum route binding #41776

wants to merge 2 commits into from

Conversation

Propaganistas
Copy link
Contributor

@Propaganistas Propaganistas commented Apr 1, 2022

This PR introduces "custom key" support for implicitly bound enums in routes, similarly to Eloquent models.

Route::get('{category:slug}', ...);
enum Category: int {
    case People = 1;
    case Fruits = 2;

    public function slug(): string
    {
        // Up to the developer to define this...
        return match($this) {
            self::People => 'people',
            self::Fruits => 'fruits',
        };
    }
}

Rationale
An enum is often used as a model attribute to simplify DX while still efficiently persisting integers in the database. There are ample of situations where a model's enum would be included in a route as well. Currently Laravel is only able to implicitly resolve string-backed enum route bindings, but that sort of contradicts the aforementioned use case.

One could of course go with explicitly defining such an enum route binding. But since implicit model binding features a custom route key I figured a similar feature would fit the enum binding as well.

Considerations
The implementation of the desired "key" method is not airtight. It's up to the developer to define a value for every enum case. However, this can also be seen as an opportunity: a specific case can simply be omitted to make the binding return a 404 for that case...

Original PR for implicit enum binding
#40281

@Propaganistas Propaganistas changed the title push Custom key support for implicit enum route binding Apr 1, 2022
@taylorotwell
Copy link
Member

Personally I wonder if this would be better solve by the addition of a whereIn regex helpers on routes (like whereAlpha), etc.

Route::get('/foo/{bar}')->whereIn('bar', Category::slugs());

Where slugs returns an array of valid values. This feels like a more flexible approach that can solve a variety of use cases, including this one. Feel like taking a stab at that?

@taylorotwell
Copy link
Member

CreatesRegularExpressionRouteConstraints is the file you would be interested in.

@Propaganistas
Copy link
Contributor Author

@taylorotwell On a further thought, this implementation might still be worthwhile to consider in light of parameter injection:

If the enum is string-backed, implicit route binding would return an instantiated enum:

Route::get('/foo/{bar}', function($bar) {
    // $bar is an instantiated enum
});

Using the implementation put forward in this PR, binding to a custom key would also return an instantiated enum:

Route::get('/foo/{bar:slug}', function($bar) {
    // $bar is an instantiated enum
})->whereIn('bar', Category::slugs());

While the newly added whereIn constraint would return the plain parameter string:

Route::get('/foo/{bar}', function($bar) {
    // $bar is a string
})->whereIn('bar', Category::slugs());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants