Symfony include static html in template - symfony

I just started to learn how to use Symfony which i believe is straight forward but i have a little problem with the templating engine. I want to include a static HTML fragment in one of my twig templates in Symfony (2.5.6). For now i created a static subfolder inside the resources directory (this might change but it definitely won't be inside the view folder). However i can't get this done, i always end up with an unable to find template error. I find the documentation on this subject a bit sparse (see http://symfony.com/doc/current/book/templating.html#including-other-templates) also the twig docs can't help me out on this one. I'm not even sure if i can use the magic #Bundle notation or if i have to reside in the view folder as ../ notation is not allowed within the include tag.
I tried the following (and a couple of variations):
{{ include('#FashionMediaBundle/Resources/static/pricing.html') }}
I guess symfony cannot handle raw html in include but i could use a php template without any template tags as well, so the question is just how to specify a location outside the view folder.
I know of http://github.com/kgilden/KGStaticBundle which will probably solve my issue but i can't believe that is not achievable with the default configuration.
EDIT: i just tried to include a regular template file from the very same directory specifying just the name of the template file (as done in the docs, see link above). Still i get an error also complaining it expects bundle:section:template.format.engine as its format. Is there an error in the docs?

Looks like the poster found the solution while I was typing. I guess I'll leave this here for just a bit.
Creating and using twig namespaces is discussed here: http://symfony.com/doc/current/cookbook/templating/namespaced_paths.html
By default, each bundles get's it's own namespace pointing to the views directory. You can add additional directories by adjusting app/config.yml
twig:
debug: %kernel.debug%
strict_variables: %kernel.debug%
paths:
"%kernel.root_dir%/../../cerad2/src/Cerad/Bundle/FashionMediaBundle/Resources/static": FashionMedia
Load the template with: '#FashionMedia/pricing.html'
I won't go into all the details but you can also use a compiler pass(http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html) to add additional paths from inside the bundle itself without having to adjust config.yml:
class Pass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$bundleDirAction = $container->getParameter('cerad_api01__bundle_dir') . '/Action';
$twigFilesystemLoaderDefinition = $container->getDefinition('twig.loader.filesystem');
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($bundleDirAction, 'CeradApi01'));
}
}

Try this:
{{ include('FashionMediaBundle:Resources:static:pricing.html') }}
If you want to put this file in another directory I suggest you to use a symbolic link (I don't know if Twig can include a file which is not in the Resources directory).

I found the Solution!
In the twig configuration you can set paths and assign a name to them.
twig:
[... twig options here ...]
paths:
"%kernel.root_dir%/../[path to static]": static_pages
And then you can include them in
{% include "#static_pages/pricing.html.twig" %}

Related

How to use Symfony TwigComponent from bundle

I am using symfony 5.4.
I have a bundle located in my vendor folder that works fine.
I have created a LiveTwigComponent.
It works perfectly when the template file 'network_list.html.twig' is located in my 'templates/components' folder.
As the logic belongs to my Bundle, i have tried to move it to the 'src/Resources/views/components' folder.
If I do so, I have an error:
"Unable to find template "components/network_list.html.twig"
In my template, I call the component like this
{{ component('network_list') }}
I have tried to prefix with the bundle namespace as it works for the other templates I have in my bundle
{{ component('#MyFooBarBundle\\network_list') }}
and
{{ component('#MyFooBarBundle\\components\\network_list') }}
but doesn't work either, I have another error message
An exception has been thrown during the rendering of a template ("Unknown component "#MyFooBarBundle\components\network_list". The registered components are: network_list").
I suspect I may have to add a config line for twig to tell the bundle to look into my bundle subfolder and i didn't find any documentation about this.
What am i doing wrong ?
Thanks in advance
The default path is located in config/packages/twig.yaml, if you wish to change the default path you can do so here. If you want to add multiple locations, you can do so by adding them to the 'paths' section and defining the file type. The code below should work for your use case:
# config/packages/twig.yaml
twig:
default_path: '%kernel.project_dir%/templates'
paths:
'%kernel.project_dir%/assets/css': css
'%kernel.project_dir%/src/Resources/views/components': twig
You can customize the template used to render the component by passing it as the second argument to the AsTwigComponent attribute:
- #[AsTwigComponent('network_list')]
+ #[AsTwigComponent('network_list', template: '#MyFooBarBundle/network_list.html.twig')]
class NetworkListComponent
{
// ...
}

How would I go extending timber to be able to use handles as references in includes?

We use fractal.js with a twig engine to prototype websites. Fractal.js brings a handy functionality to be able to use handles in includes.
So instead of writing {% include 'templates/components/teaser/basicTeaser.twig' %}, you can just write {% include '#basicteaser' %}. See: https://fractal.build/guide/core-concepts/naming.html#referencing-other-items
Of course that relies on unique components names, which I am happy to have anyway.
Could anybody point me in the right direction on how to extend timber or twig to use such handles?
Many thanks!
Twig already offers the option to load templates from an array of directories rather than just one.
$loader = new \Twig\Loader\FilesystemLoader([$templateDir1, $templateDir2]);
Plus, before passing the loader to the environment object, you can add paths for custom namespaces, i.e.:
$loader->addPath($templateDir, 'admin');
Then you can use you namespace like this:
$twig->render('#admin/index.html', []);
https://twig.symfony.com/doc/3.x/api.html#built-in-loaders
I know this is an old question and this might not be relevant to the OP anymore, but we needed the same thing and developed a WordPress plugin to bridge Timber + Fractal. You can export your Fractal components to the components-map.json file, then the loader will read the map and convert those component names to file paths.

How do I load this form theme from my App Bundle? (symfony)

I have an app with the following directory structure in Symfony 2.6
src/
App/
MainBundle/
Forms/
template.html.twig
And I'm trying to use this as a form theme along with the bootstrap3 theme. According to the documentation I can apply multiple themes. So I've updated config.yml to look like this:
# Twig Configuration
twig:
form:
resources:
- 'bootstrap_3_layout.html.twig'
- 'AppMainBundle:Forms:template.html.twig'
However, when I add the second resource I only get a blank page. It must be something to do with the way I'm referencing the template -- I can reference another one of the built-in ones and it works correctly.
Thanks.
Templates need to be saved under the
src/{bundle name}/Resources/views/{subdir}/{twig filename}
e.g.
AppMainBundle:Forms:template.html.twig:
src/App/MainBundle/Resources/views/Forms/template.html.twig

template twig not found

I have a problem with a render function in my controller.
I have:
a bundle, named CoreBundle
a controller named DefaultController
in which I have an action named loginAction
in which I am trying to render a template twig with this line
return $this->render('FooCoreBundle::Default:layout.html.twig', array());
I am always having the same not found error for the template. I have tried with an other template twig it is the same problem. In my views folder I have a Accueil folder in which i have put the login.html.twig template I want to render.
I tried to replace it directly in views folder but no changes. Sorry for my english hope you can help. Thank You.
A worth-while reading piece of info from the documentation:
Symfony uses a bundle:directory:filename string syntax for
templates that live inside a bundle. This allows for several types of
templates, each which lives in a specific location.
Supposing:
FooCoreBundle is your bundle -> src/Foo/CoreBundle
Default is the template directory -> src/Foo/CoreBundle/Resources/views/Default
layout.html.twig is your file -> src/Foo/CoreBundle/Resources/views/Default/layout.html.twig
Then the route you should use would be 'FooCoreBundle:Default:layout.html.twig' without the :: you're using in 'FooCoreBundle::Default:layout.html.twig'
The :: refers to a base template specific to the bundle. If you used FooCoreBundle::layout.html.twig then your template should live at Resources/views/layout.html.twig inside FooCoreBundle.
Hope this clarifies things.
You should use
return $this->render('NeobeCoreBundle:Default:Accueil:layout.html.twig', array());
No double colon, add the Accueil subfolder
It is not really an answer, but it could be handy for those who arrives here with symfony 4.
In documentation authors says do not organize your business logic into bundles.
In modern Symfony applications, it's no longer recommended to organize your business logic using bundles.
Of course you can, just not recommended. See here.

define custom filesystem path for twig templates

I've already read How does Symfony2 detect where to load templates from? and another ton of articles on the web
The question was quite similar to mine, but the answer wasn't comprehensive.
I need to override a bundle-defined template inside another custom bundle. In other words I want specify another path where symfony have to look before looking in app/Resources when loading templates.
Workflow should be something like this:
first: /src/My/Bundle/Resources/views/example.html.twig (or /src/My/Bundle/OriginalBundle/views/example.html.twig)
then: /app/Resources/OriginalBundle/views/example.html.twig
finally: /src/Original/Bundle/Resources/views/example.html.twig
The standard app/Resources -> src/Original/Bundle isn't enough.
sorry for my poor english and thank you
There's a native feature to do exactly what you want in a nice way. Escentially you can add a twig namespace to the twig configuration in app/config.yml like this:
twig:
# ...
paths:
"%kernel.root_dir%/../vendor/acme/foo-bar/templates": foo_bar
This creates an alias to the folder vendor/acme/foo-bar/templates and then you can use it to render your templates either from the controllers:
return $this->render(
'#foo_bar/template.html.twig',
$data
);
or from other twig templates
{% include '#foo_bar/template.html.twig' %}
Source: official cookbook http://symfony.com/doc/current/cookbook/templating/namespaced_paths.html
To add a directory for twig templates I do this:
chdir(__DIR__);
$this->container->get('twig.loader')->addPath('../../../../web/templates/', $namespace = '__main__');
this allows me to put twig templates in a folder called 'templates' in the web folder and symfony 2.3 has no issues loading them.
The class responsible for loading twig templates is stored at the service id twig.loader, which by default is an instance of Symfony\Bundle\TwigBundle\Loader\FilesystemLoader, and the class for locating templates is stored at the service id templating.locator and by default is an instance of the class Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator (which itself is injected as the first parameter to twig.loader)
So, in theory, all you would need to do is write your own class that implements Symfony\Component\Config\FileLocatorInterface (or extends Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator) and then inform the configuration to use your class (which I was going to look up how to do this for you, but Symfony's websites are down right now)

Resources