-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Routing] Allow defining and reusing subroutines #26529
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
Conversation
ef61470
to
cd086b7
Compare
@@ -78,6 +78,12 @@ public function load($file, $type = null) | |||
} | |||
|
|||
foreach ($parsedConfig as $name => $config) { | |||
if ('_subroutines' === $name && \is_array($config) && !isset($config['resource']) && !isset($config['path'])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why check against for resource
and path
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for BC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we trigger a deprecation if somebody tries to use _subroutines
as a route name here?
cd086b7
to
fe5886e
Compare
998885f
to
6b68fd8
Compare
PR is tested and ready. We just need to agree on the vocabulary. |
we already support di parameters for route requirements, don't we? that already solves the same problem from what I can see. |
IMO this not really the same thing. I think it is better to have it in the routing component, while using DI parameters can be useful in some points (including in these "subroutines"). Maybe even deprecating using di parameters could be the way to go ? |
DI parameters are not really a good extension point for this imo. This could work in theory, but I rather not refer to DI parameters at all.
|
I love @Tobion proposal! You can use something that is already implemented, it works and you already know ... instead of inventing a very similar feature, implement it, document it, learn it, etc. In practice, the differences would be minimal: This already works# config/services.yaml
parameters:
routing.uuid: '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' @Route("/foo/{bar}/", "requirements": {"bar": "%routing.uuid%"}) This would need to be implemented# config/packages/routing.yaml
routing:
_subroutines:
uuid: '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' @Route("/foo/{bar<(?&uuid)>}/") |
@javiereguiluz if I have a re-usable bundle that provides a regex for UUID, I'd have to depend on a DI parameter in my controller, which is something i try to avoid, hence I'm proposing a more robust extension point with nicer DX for this. |
The nice thing about subroutines is that they fit the routing domain, whereas parameters are a layer on top of routing. The very fact that the #26524 RFC has been open is a signal that using parameters for this is not natural. Parameters are global things, subroutines are domain-local ones. Looking at the implementation, this fits nicely and improves the component, standalone. |
IMO we should allow either or. So when this feature is really necessary, using parameters should get deprecated. There is no point in having two conceptually different solutions for the same thing. |
But then you still have no replacement for di parameters in other parts of the route definition like the path itself. So this solution here looks inferior.
If you create a symfony bundle, you rely on the DI already. So there is no difference if you use a parameter or not. Also this does not mean you need to "expose" the parameter at all. You can add semantic config for this that sets the parameter internally. So this argument does not make sense to me. |
Well, there is a difference between them:
Yes, you can use parameters for "factorization", but that's a hack IMHO (and also why nobody used them like that apparently.) |
Re-reading this, I'm still thinking this is a useful addition to the component, especially when it is used standalone. Let's make the best router out there. 4.1 already made it great. |
I don't agree. There are so many solutions to this already outside the routing component that the routing component does not need to deal with this. Apart from DI parameters, people could also use YAML named references. |
These don't work across files do they? The great thing about attributes is that you can define them and use them anywhere. With subroutines, you can defined them at the root and reuse them in imported routes (yes this is fragile, but also allows for some flexibility). Honestly, I completely forgot you can use parameters in a requirement/default 🤦♂️ |
Could a bundle define a subroutine that the application could use for its routing? |
@derrabus yes (and also for parameters as you know) |
I would rather see generic solution for reusable parameters on YAML parser level. Would be nice to do Problem with DI parameters are:
|
Yup, but you are considering only yaml loaders. What about the other ones ?
|
Other formats already have those, don't they? In PHP you can define variables, in XML you can also define common values, that's how billion laughs attack happened. Only loaders need to be changed to propagate these to children resources. |
There is a technical difference with the "loader-time" alternatives: PCRE limitations. By making PCRE aware of factorarization as allowed by subroutines, we create smaller regexp. Could be significant if all your URLs contain e.g. a uuid. Subroutines allow better scalability. |
6b68fd8
to
547184f
Compare
@nicolas-grekas would that mean that if you have |
547184f
to
fe2ed67
Compare
@iltar I don't think it would help for simple requirements, but for more complex ones, yes. |
I'm closing here as it looks like the existing alternatives are good enough. Can be reopened later of course. |
Now there is no alternative in Symfony5, or? |
Using parameters is the alternative. |
Tested locally:
It works well :)
Here are the remaining steps:
XmlFileLoader
RoutingConfigurator
UrlMatcher