简体   繁体   中英

calling PHP business logic from parent Twig templates

In my Symfony2 project I use Twig templates to render the HTML, and I need an "application-bar" to be included each one of the website's pages. The contents of this bar depend on who the user is, what privileges she has, etc. (in other words, there's a bit of business logic that needs to be executed behind the scenes). The obvious solution would seem to be to add the app-bar in the base template (since it needs to appear on each page). The problem with this however, is that it's not clear how the business logic is to be executed from the base (parent) Twig template.

@Flukey had a similar problem in this question , where his solution is to render a sub-controller from within a twig template, thereby forcing the execution of a secondary controller. To be explicit, his solution looks as follows:

{# ::base:html.twig #}
<!DOCTYPE html>
<html>
    <head>
        <title>blah</title>
        {% block stylesheets %}{# default styles #}{% endblock %}
    </head>
    <body>
        {# Question: is there a way to do add the app-bar without "render"? #}
        {% render url('app_bar_route') %} 
        {% block body %}{% endblock %}
        {% block javascripts %}{% endblock %}
    </body>
</html>

And the child:

{# AcmeDemoBundle:userpage.html.twig #}
{% extends '::base.html.twig' %}
{% block body %}user content here; Twig file rendered from "primary" PHP Controller.{% endblock %}

In order for the render to work, we also require the route to be defined:

# routing.yml
app_bar_route:
    pattern:  /sitestructure/appbar
    defaults: { _controller: SiteManagerBundle:AppBar:index }

But this solution lies very uneasily with me for the following reasons:

  • Firstly, this solution means that you have to manage separate new URL for each navigation-bar on your site
  • Secondly, there is a separate URL for every nav-bar on the site ( http://mysite/sitestructure/appbar in the example above), which just seems very messy
  • Thirdly, there is also this concern about performance , which I find very sensible concern. I don't see why each individual user-request to an HTML page should result in two (or three or four) physical requests being sent to the server -- an extra render request for each nav-bar on the site (more nav-bars are likely to be added as the site gets more complex).

So is there a better way to do this? Is it possible to use Twig's {% include %} functionality instead of {% render %} , and if so, how does the business logic for the base template get executed?

EDIT : To clarify, the type of 'business logic' that I refer to will require making database calls -- it's not the type of logic I want to code into the template, so I need somehow to get back into a PHP class/function.

EDIT2 : Should I really be worrying about making calls to sub-controllers? Perhaps I misunderstood the way the render engine works. I assumed that this would generate a second HTTP request to the web-server (obviously not from the Web browser, but an internal one from the server itself). To me, this would seem to imply quite large overheads, not to mention increased chance of producing some kind of response error. But then maybe I have misunderstood the framework, in which case, please educate me!

I'm not sure I understand all of your points.

You can certainly make a app_bar template and include it in your base template:

<body>
    {{ include('@MyBundle/app_bar.html.twig') }}
    {% block body %}{% endblock %}
</body>

You can certainly show different items in app_bar based on the user

{% if is_granted('ROLE_ADMINx') %}
    <li><a href="{{ path('zayso_natgames_admin') }}">Admin</a></li>
{% endif %}

It's not clear what other sort of "business logic" you need. If it goes beyond simple conditionals then you could put the code in a twig extension.

I sort of get the impression that you need more? Multiple types of app_bar perhaps? I don't understand the stuff about "each navigation bar" needs something special.

It's possible that you may have a misunderstanding about how sub controllers are implemented. Sub-controller requests are done internally. No round trip to the browser. Performance impact is minor. No need for multiple url's, Just one route_app_bar.

Unless of course I completely misunderstood the question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM