Parameterizable model-binding #54515
Replies: 2 comments 1 reply
-
I've had this same issues and have been trying to come up with a simple and maintainable solution for it. I am actually working an a possible PR to add an attribute that can be used in controllers to mark a method as the query resolver for a specific binding that corresponds to a specific model class. The resolver would either build on the default query or return an entirely new query if needed. It would look something like the code below. I'm curious if this would be helpful for your situation as well? class UserController extends Controller
{
#[ImplicitBindingQueryResolver('user', UserModel::class)]
public static function resolveUserQuery(Builder $defaultQuery): Builder
{
return $defaultQuery->where('canWriteComments', true);
}
public function show(UserModel $user)
{
return $user->getKey();
}
} |
Beta Was this translation helpful? Give feedback.
-
Hi. Maybe our parallel approach to route model bindings can help you. For example you can overwrite the controller getRelated function and introduce additional conditions for both relation or resource on a route that looks like
Another thing is that when you call GET |
Beta Was this translation helpful? Give feedback.
-
Premise:
Bindings are global cannot be spaced to distinguish between e.g. web and api-routes.
Identifiers for bindings are strings and strings can have collisions.
e.g. (A very contrived example)
User(for the user of the application) and CommentingUser (which has additional conditions(e.g. permissionflag to comment set).
Both are users. Within the request handler it should not matter what condition the user was loaded with.
We would have to maintain dedicated bindings though(at least for CommentingUser).
(And, no, this particular example cannot be solved by gates as the User is object and not subject of the operation.)
Proposition:
Aside from namespacing bindings(which may be a bigger undertaking , discounting that consistency that {user} binds User anywhere in routes(implicit or explicit) or subclassing where CommentingUser extends User- with additional global scopes causing artificial distinctions making the overall handling of this brittle -, configurability comes to mind.
We already have this mechanism in the middleware where we can give parameters to the middleware (e.g.
can:......
).Yes,
:
etc. are special chars in routing. However, we have two sides to this:We already consider EVERYTHING between
{
and}
to be part of the binding. By that token there shouldn't be any difference between{foo}
and{foo:bar,barfoo}
.While handling this with a dedicated or even implicit binding may be a bit more work, changing https://github.com/laravel/framework/blob/11.x/src/Illuminate/Routing/Route.php#L1308 the matching for the routes there (didn't look too closely at SymfonyRoute but matching at that point boils down to matching one string against another) to consider not just
\{\w\}
but also more chars(:
,.
,etc) would allow us to write a middleware that describes a more generic binding for our domain logic if we need to.e.g. (very contrived and verbose)
{user:key-for-search:randomNonEnumerableIdField#condition[canWriteComments]=true}
and the middleware would look for that model via
User::query()->where('randomNonEnumerableIdField', $valueToUseForModelBinding)->where('canWriteComments', true)
The benefit for this would be a coherent generalization and it would keep the logic binding models of particular types in one place.
Beta Was this translation helpful? Give feedback.
All reactions