Twig Check for partial existence before include - symfony

I am working on a fairly complex multi lingual site that will render different partials based on the html locale.
I have a partial structure that will use the locale appended to the file name to pick the right one. For example;
{% include '#BundleName/Layout/Text/_partial-name.' ~ htmlLocale ~ '.html.twig' with {'title' : resource.title } %}
Whilst this works, there is a risk if the locale selected has not (yet) had its partial created, this will throw an error. What i would like to do is check for the existence of the partial before trying to render it and fall back to a default if it does not yet exist.
{% if '#BundleName/Layout/Text/_partial-name.' ~ htmlLocale ~ '.html.twig' %}
{% include '#BundleName/Layout/Text/_partial-name.' ~ htmlLocale ~ '.html.twig' with {'title' : resource.title } %}
{% else %}
{% include '#BundleName/Layout/Text/_partial-name.html.twig' with {'title' : resource.title } %}
{% endif %}
Obviously that doesn't work, but that's the kind of thing i am after!

Rather than to test if the partial exists you can use ignore missing:
{% include 'partial.html' ignore missing %}
If you do wish to have a fallback when the file is missing you can pass an array to the include function. This will make the include render the first found template in the array
{% include [
('#BundleName/Layout/Text/_partial-name.' ~ htmlLocale ~ '.html.twig'),
'#BundleName/Layout/Text/_partial-name.html.twig'
] with {'title' : resource.title } %}

You can use |default twig filter to determine a default value to a variable if the value is undefined or empty :
htmlLocale|default('en')
You can also check if the variable is empty and/or defined :
{% if htmlLocale is not empty and htmlLocale is defined %}
{% include '#BundleName/Layout/Text/_partial-name.' ~ htmlLocale ~ '.html.twig' with {'title' : resource.title } %}
{% else %}
{% include '#BundleName/Layout/Text/_partial-name.html.twig' with {'title' : resource.title } %}
{% endif %}

Related

Symfony2 Twig Conditional Template Name

I'm looking for a way to check in my twig template if the name of the template contains a special word. If that is the case I want to proceed with assigning some stuff. Here is a general idea I have in mind.
{% if [sth like app.request.template_name or sth like that] in `product` %}
// Do some stuff
{% endif % }
Can you guys help me with this?
If you're creating separate template files then you'll know the names and can hardcode the values:
template_1.html.twig:
{% set some_var = 1 %}
{% set another_var = 2 %}
template_2.html.twig:
{% set custom_var = 5 %}
Update:
If you want the template name, you can use:
{% if 'product' in _self.getTemplateName() %}
{# Do stuff #}
{% endif %}

Set a Variable with a Twig Macro

I have to set a variable with a macro, that returns a number, so I have this macro:
{% import _self as self %}
{% macro function_size(field) %}
{% import _self as self %}
{# initial Setup #}
{% set field_length = 0 %}
{# Field #}
{% for key, value in field %}
{% if not (key starts with "#") %}
{% set field_length = field_length + 1 %}
{% endif %}
{% endfor %}
{{ field_length }}
{% endmacro %}
The Macro loops through the entries of a field and returns the count of values, that don't start with "#".
So I set a variable with that value:
{% set image_size = self.function_size(content.field_teaser_image) %}
ATTENTION: With this you will set the Variable with Twig Markup. (You can see that when you debug the variable afterwards.)
To get a number/integer as value you have to convert it to a String (that will be interpreted as a number if you calculate with it)
{% set image_size = image_size.__toString %}
With this I set the Variable successfully with a macro.
My Question: Is this a bad practice, are there better ways how to set an Variable?
Thank you!
Two ways to set variables for twig are fine in my opinion.
1. Use theme and other hooks (inside theme or any module) and pass variable from php,
2. create twig extension/filter
Examples:
Filter:
http://leopathu.com/content/create-custom-twig-filter-drupal-8
Extension:
http://symfony.com/doc/current/templating/twig_extension.html

symfony twig : add a class while keeping the existing ones

In a template, I am using the following code to add a class to an element :
{% set attr = field.vars.attr|merge({'class':'input-sm'}) %}
{{ dump(attr) }}
{{ form_widget(field, attr) }}
the dump shows the array with the input-sm class but the control does not have it.
If I do it without the merge, the classes defined in my type are overriden, and I don't want that, I want to keep both classes defined in my type and defined in my template.
Does someone knows how to solve this?
EDIT:
I corrected a first mistake. But then the classes defined in my type are overriden
{% set attr = field.vars.attr|merge({'class':'input-sm'}) %}
{{ form_widget(field, {'attr' : attr}) }}
Solved it!
Solution :
{% if field.vars.attr['class'] is defined %}
{% set class = field.vars.attr['class'] ~ ' input-sm' %}
{% else %}
{% set class = 'input-sm' %}
{% endif %}
{% set attr = field.vars.attr|merge({'class': class }) %}
{{ form_widget(field, {'attr' : attr}) }}

Unable to find template Symfony2

I would like to include a template in my view but it doesn't work, I have this error :
Unable to find template "::StyleBlock/light-pattern.html.twig" in ::base.html.twig at line 46.
My code :
{% for zone in content.blocks %}
{% set path = '::StyleBlock/' ~ zone.styles %}
{% include path %}
{% endfor %}
In the details i have this message :
InvalidArgumentException: The file "views/StyleBlock/light-pattern.html.twig" does not exist (in: /var/www/gathena/app/Resources).
But the path is correct, i don't understand.
I use Symfony 2.3 and I have the good permission on my directory
You have given wrong path, it should be:
{% for zone in content.blocks %}
{% set path = 'CmsCmsBundle:StyleBlock:' ~ zone.styles %}
{% include path %}
{% endfor %}
as for path src/Cms/CmsBundle/Resources/views/StyleBlock/
The first parameter is your bundle, second is the controller in this case StyleBlock, so your views are in your bundle in Resources/views/StyleBlock directory, last parameter is the template name which is defined by your loop variable in this case. It should only be your template name, without any absolute paths. All parameters are seperated by :
Try this :
::StyleBlock:light-pattern.html.twig

How do you check if an object exists in the Twig templating engine in Symfony2?

I have a multidimensional array where some objects exist and others don't. I keep getting a
Method "code" for object "stdClass" does not exist in...?
The code I am using in my template is:
{% for item in items %}
<p>{% if item.product.code %}{{ item.product.code }}{% endif %}</p>
{% endfor %}
Some products do not have this code and unfortunately this data structure is provided via a feed, so I cannot change it.
When I looked at the Twig documentation I interpreted that if an object or method was not there it would just return null?
Quickly did a lookup, hope this is works for you :p
defined
defined checks if a variable is defined in the current context. This is very useful if you use the strict_variables option:
{# defined works with variable names #}
{% if foo is defined %}
...
{% endif %}
{# and attributes on variables names #}
{% if foo.bar is defined %}
...
{% endif %}

Resources