Skip to content

[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

Closed
wants to merge 2 commits into from

Conversation

vmonjaret
Copy link

@vmonjaret vmonjaret commented Sep 24, 2018

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets -
License MIT
Doc PR -

Added a method hasRoute to check if a route exists or not

Signed-off-by: vincent monjaret <vmonjaret@gmail.com>
@vmonjaret vmonjaret changed the title [Routing] UrlGenerator: add a method 'hasRoute' to check whether a route exists # [Routing] add a method to check if a route exists Sep 24, 2018
Copy link
Member

@nicolas-grekas nicolas-grekas left a 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)
Copy link
Member

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

Copy link
Member

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

Copy link
Member

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);
Copy link
Member

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);
Copy link
Member

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
Copy link
Member

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)
Copy link
Member

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

@nicolas-grekas nicolas-grekas changed the title [Routing] add a method to check if a route exists [FrameworkBundle][TwigBridge] add a method to check if a route exists from controllers and twig templates Sep 24, 2018
@@ -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')),
Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Member

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!)

Copy link
Contributor

@linaori linaori Sep 24, 2018

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.

Copy link
Contributor

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?".

Copy link
Member

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?

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Member

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.

@nicolas-grekas nicolas-grekas added this to the next milestone Sep 24, 2018
@voronkovich
Copy link
Contributor

@vmonjaret, please see this issue: symfony/symfony-docs#6710

@fabpot
Copy link
Member

fabpot commented Sep 25, 2018

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.

@nicolas-grekas
Copy link
Member

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 :)

@nicolas-grekas
Copy link
Member

See also #19270

@fabpot
Copy link
Member

fabpot commented Sep 25, 2018

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 generate exception. So, it means that it is possible to check a route, but in a slightly more difficult way than having a proper hasRoute() method (which is good enough IMHO).

@nicolas-grekas
Copy link
Member

Thanks for the confirmation, works for me! Sorry for asking twice.

@vmonjaret vmonjaret closed this Sep 25, 2018
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.2 Nov 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants