Symfony2: How to properly include assets in conjunction with Twig template inheritance?

Iniquities of evil men picture Iniquities of evil men · Sep 16, 2012 · Viewed 7.8k times · Source

I'm currently developing a web application using Symfony 2.1.0.

I've read through the Templating chapter of the book and I'm trying to include assets (right now, it's just a single stylesheet) in my web pages.

I'm using the Three-level inheritance system that is mentioned in the book, and my application structure currently looks like this:

  • app/Resources/views/
    • base.html.twig: base template, containing title, stylesheets and body blocks.
  • src/My/PageBundle/Resources/views
    • layout.html.twig: layout template (extending the base template), appending the main stylesheet to the stylesheet block, and overwriting the body block, including navigation.html.twig and defining a content block
    • layout-admin.html.twig: same thing as above, but including navigation-admin.html.twig
    • src/My/PageBundle/Resources/views/Main
      • standard templates, extending the layout template and overwriting its content block
    • src/My/PageBundle/Resources/views/Administration
      • administration templates. Same thing as above, but extending the administration layout template.
  • src/My/PageBundle/Resources/public/css
    • main.css: main stylesheet

As you can see, I have put the stylesheet in my bundle. I don't know whether this is good practice or not.

Now, the thing is, in layout.html I added this:

{% block stylesheets %}
    {{ parent() }}

    <link rel="stylesheet" type="text/css" href="{{ asset('css/main.css)' }}" />
{% endblock %}

But asset('css/main.css') is just linking to /css/main.css, whereas ./app/console assets:install installs the assets in web/bundles/mypagebundle/. I don't like the fact that this way, my bundle name would be publicly visible (which could make users suspect I'm using Symfony, and I like keeping the internals of my webpage, well, internal). Is it possible to change the directory where assets:install would install the assets? It seems tedious to me to manually install the assets in web/.

I'm also thinking about using Assetic for asset management, as I personally like the possibility to automatically minify my scripts/stylesheets and store them all together in one file. However, I hear that this is not possible if you include stylesheets at different levels, i.e. it wouldn't work with the three-level inheritance system. Is it possible to work around that? Also, would using Assetic enable me to hide my bundle name from the public?

Answer

Arnaud Le Blanc picture Arnaud Le Blanc · Sep 16, 2012

Using assetic would address all your issues.

I hear that this is not possible if you include stylesheets at different levels, i.e. it wouldn't work with the three-level inheritance system

You can, but it will generate a css file for each level (just like with asset(), actually).

Example:

layout:

{% block stylesheets %}
    {{ parent() }}
    {% stylesheets 'main.css' %}
        <link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
    {% endstylesheets %}
{% endblock %}

sub-template:

{% block stylesheets %}
    {{ parent() }}
    {% stylesheets 'sub.css' %}
        <link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
    {% endstylesheets %}
{% endblock %}

result:

<link rel="stylesheet" type="text/css" href="..." />
<link rel="stylesheet" type="text/css" href="..." />

Alternatively sub-template can completly override the stylesheets block, so that only one stylesheet is generated (but it's less dry):

{% block stylesheets %}
    {% stylesheets 'main.css' 'sub.css' %}
        <link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
    {% endstylesheets %}
{% endblock %}

result (in production / non debug):

<link rel="stylesheet" type="text/css" href="..." />