-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[FrameworkBundle][TwigBridge] add a method to check if a route exists from controllers and twig templates #28578
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
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.
Thanks for giving this a try.
Here are some comments.
|
||
public function __construct(UrlGeneratorInterface $generator) | ||
public function __construct(UrlGeneratorInterface $generator, RouterInterface $router) |
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.
adding a new mandatory arg is a BC break: you need to make it optional and deal with this possibility in the code
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.
Thus, this makes it impossible to use this extension in a context not using the full RouterInterface, but using only the UrlGeneratorInterface and MatcherInterface interfaces
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.
correct, and actually having an UrlGeneratorInterface
is enough to implement the logic!
*/ | ||
public function hasRoute(string $name) | ||
{ | ||
return $this->router->getRouteCollection()->has($name); |
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.
calling getRouteCollection is a no-go as it is very slow
instead, I'd suggest trying to generate a route with that $name and catch the exception to return false
*/ | ||
public function hasRoute(string $route) | ||
{ | ||
return $this->container->get('router')->getRouteCollection()->has($route); |
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.
same as above: calling getRouteCollection is too slow to be effective
* | ||
* @param $name | ||
* | ||
* @return bool return true if the route exists, false if not |
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 be replaced by a real return type
actually I think the docblock itself doesn't provide much info over the signature so it could be remvoed, isn't it?
* | ||
* @return bool return true if the route exists, false if not | ||
*/ | ||
public function has($name) |
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.
missing "string" type hint on $name
@@ -42,6 +45,7 @@ public function getFunctions() | |||
return array( | |||
new TwigFunction('url', array($this, 'getUrl'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), | |||
new TwigFunction('path', array($this, 'getPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), | |||
new TwigFunction('has_route', array($this, 'hasRoute')), |
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.
I don't think this should be possible in twig. Generating routes is one thing, but giving the developer the ability to check if a route exists, sounds like a poor solution to see if certain features are available. I think it's better to toggle those features using different means, such as a feature bundle or true/false coming from the controller.
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.
if it's possible in a controller, it should be in twig also to me, allowing building flexible systems.
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.
It's also possible to make a soap call in a controller, that doesn't mean it should be possible in twig. Enabling links based on whether a url can be generated or not, will become a mess to maintain, which is something I rather see solved in a proper way, but is very domain specific.
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.
What's the relation to soap? We can go in very lengthy unrelated comparisons without making any progress on this one for sure...
This PR is about #19273 (link missing in the description btw!)
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.
The idea of templating is to contain as little logic as possible (soap call, check if route exists, call something from a repository). If there is any, it should be hidden from the implementation and only ask whether something should be done or not. In this scenario that would mean that you want to do X or Y based on whether a route exists, this logic should be in your controller and tell your template what to do.
I have no objections to making this available in the router and if developers wish to implement this twig function in their project, that's their choice. I don't think this should be in the Symfony core as the framework should promote correct usage of templating. The AbstractController could even support a shortcut to make it easier to use.
class FooController extends AbstractController
{
public function fooAction()
{
return $this->render('foo.html.twig', [
'should_show_link_x' => $this->routeExists('app.route_x'),
]);
}
}
{% if should_show_link_x %}
<a href="{{ path('app.route_x') }}">Route X</a>
{% endif %}
{# vs #}
{% if has_route('app.route_x') %}
<a href="{{ path('app.route_x') }}">Route X</a>
{% endif %}
In normal scenarios, you control the routes, you know which routes exist, so to me this looks like an extension point in bundles or some form of modules. I don't think this is the right way of checking this extension point. The presence of a route should not define whether a specific feature is enabled or not. Not only is this very fragile, it also means that during container compilation you don't know whether or not a specific feature will be present, making it an inefficient way of enabling or disabling features.
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.
is_granted()
is calling the abstraction layer to grant permissions, while has_route()
is a direct check to see if a route exists, there is no abstraction at play here. If it was is_feature_enabled('foo')
, it would be a different story. If someone adds a route "because it doesn't exist and this link is not displayed", there's no question and it can just be added. There won't be anyone asking "why is this feature not present, how do I get this feature?".
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.
@voronkovich maybe you'd like to chime in here? WDYT?
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.
@nicolas-grekas, I agree with @iltar. I think we don't need a twig function. Having the routeExists
method in the controller is enough.
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.
Fine to me then, thanks.
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.
I also agree with @iltar here, having has_route
available by default in Twig sounds weird to me.
@vmonjaret, please see this issue: symfony/symfony-docs#6710 |
I'd like to challenge the needs for such a feature. As @iltar said, it is probably "cleaner" to check for a feature instead of a route. I think I'm leaning toward a 👎 for adding such a feature in core. |
The issue reporter explains why he suggested we might need that method. He did so in #19273. He suggested another way btw. Should we close it also as won't fix? You pinged me on it :) |
See also #19270 |
I've read the linked issues before coming to this conclusion. And I like the fact that there is already a way to do the same really fast with catching the |
Thanks for the confirmation, works for me! Sorry for asking twice. |
Added a method hasRoute to check if a route exists or not