How can I manage Twig inheritance across multiple bundles? - symfony

I'm (still) a beginner with Symfony and have been reading about three-level inheritance with Twig.
If you define blocks in your bundle their names might be bundle specific and not match block names defined in your app base.html.twig or other bundles, or even the names could be the same but the usage could be different.
Has anyone found this to be a problem?
Are there ways to manage this, will overriding templates under app/ help?
Are there any conventions for block names or anything else that will minimise maintenance problems?

Block names should have some sort of relation to whats going to place within the block. so if you have css styles within a block you would call it Stylesheets, and for javascript files call it JavaScript. As far bundles, create a layout.html.twig within the views folder and extend the base.html.twig.

Related

Location for Symfony bundle templates

The directory structure for bundles specifies that views should be stored in <your-bundle>/Resources/views. But then the best practices for template locations says that, actually, I should store them in app/Resources/views. I can see the conveniences of doing the latter, but I don't understand:
If I am organizing things into bundles, aren't I reducing the bundles' portability by "de-bundling" the views?
The examples show that index.html.twig is easier to write than AcmeDemoBundle::index.html.twig, but what if I also have FooBundle::index.html.twig? I still need a way to specify which index.html.twig I want, right?
The documentation is correct. Store reusable bundle's templates in <your-bundle>/Resources/views and your project's templates in app/Resources/views. There is no conflict.
If you decide to create a bundle make sure it can be reused (that's the main purpose of the bundle). Otherwise keep using your AppBundle. AppBundle will not have two /index.html.twig's.

Are you allowed to create seperate ASP bundles for resources in the same directory?

Suppose I have a directory with multiple css files. Is there a way to create and reference multiple ASP bundles for the same directory?
Let's say you have a folder with several stylesheets.
I know you can include specific files by their virtual paths like this:
//Bundle1
bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
"~/Content/themes/base/jquery.ui.core.css",
"~/Content/themes/base/jquery.ui.resizable.css",
"~/Content/themes/base/jquery.ui.selectable.css",
"~/Content/themes/base/jquery.ui.accordion.css",
"~/Content/themes/base/jquery.ui.autocomplete.css"));
What if I add another bundle, and this one includes stylesheets that are in the same directory as the previous bundle?
//Bundle2
bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
"~/Content/themes/base/jquery.ui.button.css",
"~/Content/themes/base/jquery.ui.dialog.css",
"~/Content/themes/base/jquery.ui.slider.css",
"~/Content/themes/base/jquery.ui.tabs.css",
"~/Content/themes/base/jquery.ui.datepicker.css",
"~/Content/themes/base/jquery.ui.progressbar.css",
"~/Content/themes/base/jquery.ui.theme.css"));
Now that I've created the bundles, I want to reference them.
I know I can call the following if there was just one bundle for the directory
#Styles.Render("~/Content/themes/base/css", "~/Content/css")
The problem I'm having with Styles.Render though is that it only accepts a virtual path to a path. Lets say you create more than one bundle in the same directory (if that is even possible). You can't use Styles.Render to select which bundle you want. You can only give it a path. Is there another way to reference a bundle you create in BundleConfig without Styles.Render?
Or is Styles.Render is the only way to reference any style bundle in the HTML?
Are you allowed to create seperate ASP bundles for resources in the
same directory?
Yes
How would I reference these bundles with the Styles.Render method?
#Styles.Render("~/Content/CssBundle1")
#Styles.Render("~/Content/CssBundle2")
The important thing to illustrate here is the reasoning behind bundling and the intended use of it. Bundling exists to reduce the number of requests and improve the load time of your application. You could do this manually, but you would have spaghetti code to manage. The bundling is there to keep everything modularized and easily organized.
Where I think there might be confusion
StyleBundle("~/Content/magicaunicornsdacningonrainbowsthisnameisrelative")
When you create a bundle, the virtual path can be named whatever you want. You bundle it in categories that makes sense.
//Bundle1
bundles.Add(new StyleBundle("~/Content/pets").Include(
"~/Content/dog",
"~/Content/cat",
//Bundle2
bundles.Add(new StyleBundle("~/Content/cities").Include(
"~/Content/memphis.css",
"~/Content/bejing.css",
//Bundle3
bundles.Add(new StyleBundle("~/Content/people").Include(
"~/Content/joseph.css",
"~/Content/michael.css",
With the bundles created, you make sure to call the bundles in the order you need them, loading only what is needed for each page.
#Styles.Render("~/Content/pets", "~/Content/cities")
* LOTS OF STUFF LOADED HERE! BUT YOU DO NOT NEED THE PEOPLE BUNDLE RIGHT AWAY *
#Styles.Render("~/Content/people")
You would simply create a different bundle for that references all the needed files, and you would call that bundle as needed. If you need to break up the order in which a file renders scripts or styles then you have multiple bundles. MVC is a lot about proper modularization, so you're always working up towards a root or singularity.
Getting more advanced
Obviously you can kick it up a notch. The next steps include using .less or .sass preprocessors for your style bundles. Those will help with very detailed modularization. Next, you can start using variables and conditions to determine which bundles should be run, linked below.
Or is Styles.Render is the only way to reference any style bundle in
the HTML?
There are other ways to reference css files via code. For instance, you could write a simple for loop to accomplish the task of writing the needed css scripts. Additionally, you could use razor variables.
Resource
Variables in Styles.Render
http://www.asp.net/mvc/overview/performance/bundling-and-minification

Dynamically add assets via php

While we are using Assetic with Twig templating, we want to delay the actual processing until the last moment for various reasons. So instead of using the javascripts, css tags of assetic we created something like this
{{ add_asset (['public/js/prototype-handler.js', 'public/js/shipping-method.js'], 'js') }}
Anyhow, the idea is that at the end of the response event we will process and inject all assets to the content. However, right now I'm stuck at how to add these assets to assetic so they can be processed and returned with the result file(s).
I have checked some other bundles and what they are doing right now is to render the assets via twig like this:
AssetManagementBundle
However, it doesn't seem to be an optimal approach to this. I wonder if there is a better way or not?
For people who may encounter this same need, you want to use createAsset of the AssetFactory.
Then you can loop through the created assets and do what you want with them.
For more information and working code, please check our bundle here
I'm not sure to completely understand your needs but you could be interested by the AsseticInjectorBundle, it allows you to tag your resources files in a configuration file and add it by adding the tag where you want in your assetic markup, in your layout.
I don't think dealing with resources in php is a great idea and it's better to do this directly in your layout coupled with some configuration file.

Extending all templates in a bundle from the controller

I have a lot of templates in a bundle and they all extend the same layout.html.twig. Rather than have to define:
{% extends 'MyBundle::layout.html.twig' %}
at the top of every template, is there a way to do configure this?
I suspect that I would need to create a pre- or postExecute()-like method based on an event listener that extended the template before rendering.
This is not a good idea, because not every template has to extend a layout: there are some “system” templates like form_div_layout.html.twig that are not meant to extend anything. Besides, not every template you write has to extend a layout; you'll encounter a lot of use cases for small embeddable templates to reference from other templates.
If you will try to force a layout on each template, you'll have to write some logic to exclude “system” and embeddable templates so that they don't extend anything, and you'll have to do the same for your layout template too, so that it doesn't extend itself infinitely. In this case you'll reverse the problem: instead of defining explicitly which layout to extend in each template, you'll have to explicitly state which templates should not extend your layout. This will get very messy very fast.
To grasp this idea more completely, you need to know that, behind the scenes, templates are really just PHP classes. Does it make sense to you to make a particular class the parent for every other classes, and then explicitly state which classes should not extend this parent?
But if I haven't convinced you not to go this way, there is a Twig setting which lets you set the base template class for all templates:
twig:
base_template_class: Your\Layout\ClassName\Here
You can extend \Twig_Template or implement \Twig_TemplateInterface and have some “fun” for several hours, after which I hope you'll be convinced to abandon this idea whatsoever. Good luck. :)

What goes in app/Resources and what goes in Acme/MainBundle/Resources

I am starting a new project using Symfony2. I am adding some basic twig templates like my CSS template (with assetic to trigger sass -- nifty) and my header/footer template. My question is, should this sort of thing go into app/Resources or into Acme/MainBundle/Resources?
I am sure I can do either if I really wanted to, but I'd like to know what the correct way to do it is.
app
Resources
<A. here?>
src
Acme
MainBundle
Resources
<or B. here?>
It's really a matter of preference. I tend to keep global views in app/Resources. Does your MainBundle contain anything else besides views? If not, I think that's more reason to use app/Resources and avoid unnecessary bundle pollution.

Resources