Use a string variable inside an if condition in twig - php

I have a problem in twig which is below :
I want to use a variable which is a string which is a condition ( that i read from a table from a yml file) inside and if statement consider this example.
{% set condition = 'a condition' %}
{% if condition == true ]%
do something
{% endif %}
Notice : the string used as a variable contains a twig code
How is it possible to do that ??
is there any similar to eval() of php in twig ?
thanx in advance

You can use some tricky hack with is_granted function. It's created to be used for security purposes but it will work for your use case.
is_granted can evaluate Symfony Expressions, then result can be used in conditional statements.
This example works fine for your case:
{% set condition = "true" %}
{% if is_granted(expression(condition)) %}
CONDITION IS TRUTHY
{% endif %}
To make it work you need to install symfony-expressions and security components:
composer require symfony/expression-language
composer require security
Also if you don't use it for granting access for users to some places in your template it would be better to create own twig function that will execute Symfony Expressions like is_granted do.

Related

Twig include performance with and without passing variables

I am wondering what is best perfomance-wise, using
{% include "_inc/template" %}
or
{% include "_inc/template" with {'foo': bar %}
assuming foo is the only variable used in _inc/template and it's also available in global context.
Will there be significant difference in performance between two approaches, if the include is placed within for having ~50 loops?
I don't have direct answer to your question, but you can use the profiler in dev toolbar to see the timeline of the calls.
Maybe try and tell us...
Which is the version of symfony you use?
I know that in symfony > 2.7 the timeline Graph exist.
Ps : Maybe try it with this too:
{% include 'template.html' with {'foo': 'bar'} only %}

A NULL check in Twig Template is not working which leads to an error (very strange behavior)

I’m currently facing a very strange problem in a Twig template (Symfony v2.8.9; Twig v1.24.1). The basic outline is: I’m trying to overwrite a block in a child template when a specific condition is met.
Here’s a snippet of my template:
{% extends "#App/search/resultList.html.twig" %}
{% if category.teaser %}
{% block description %}{{category.teaser.doSomething()}}{% endblock %}
{% endif %}
This code leads to the following error:
Impossible to invoke a method ("doSomething") on a null variable in #App/search/categoryResult.html.twig
The teaser property of the category indeed is null, which is okay and what the check is for.
I also tried an explicit {% if category.teaser is not null %} which also didn’t work and resulted in the same error.
Now for the really weird part (or maybe I’m just not seeing it why this wouldn’t be weird):
If I change the code to
{% block description %}
{% if category.teaser %}
{{category.teaser.doSomething()}}
{% endif %}
{% endblock %}
it works as intended (mostly, at least, because the parent block will always be overwritten).
This error seems to happen only in the Symfony dev environment.
It seems:
# Twig Configuration
twig:
debug: true
strict_variables: true
has something to do with it, which explains the dev environment only. If both values are set to false it works correctly.
Has anybody ever encountered a problem like this and solved it? Any help in solving this issue would be much appreciated.
As far as I know, it is not possible to conditionally override a block in twig, see also How can I conditionally override a TWIG layout block?
You have done the best practice by testing whether the variable is null or not.
In many other languages you can’t do something on a null. You can use the dump() function to check your variables.

Using a Twig variable inside the 'use' tag

I want to dynamically use a Twig template, but for some reason I can't get it to work.
When I add this line, my page crashes:
{% use current_page %}
current_page is set to "birthday.twig", which exists.
As the Twig documentation states:
Because use statements are resolved independently of the context passed to the template, the template reference cannot be an expression.
So unfortunately it is not possible to have a variable {% use xyz %} statement.
However, you can include using a variable. See http://twig.sensiolabs.org/doc/recipes.html

Symfony2 Twig Inject additional blocks

Is there a way with Symfony2 and Twig to always make files available which just contain blocks.
For example, if I wanted to make a block named 'cookie' always available in any template in my system, without having to always include or extend it in the template I'm using.
Any ideas?
Clarification
Say I have a generic block which can do something, like:
{% block myBlock %}
ABC Examples
{% endblock %}
I have a class which knows it wants to be rendered with this block. My template itself doesn't necessarily know this though.
{{ block(myObj.blockName) }}
I would then like to have it so my controller/services/etc. could register the file which contains that block, without my template actually needing to know about it directly (so I could have multiple files like that, each working with some common interface).
Similar to registering custom Twig functions with a TwigExtension. My template doesn't need to explicitly know it's there, it just has to be available at run-time.
Does that make sense?
To clarify a bit further, I'm essentially looking to do something just like how there are default Twig blocks for rendering Forms in Symfony2. I don't have to include the default form file every time, just when I want to change something.
I went digging around in the Symfony source code to try and find my answer. It looks like there isn't some fancy, neat way to embed it from a configuration file or controller directly, which is a bit disappointing, but not a huge deal.
So, to solve my situation, I'll be using the "use" keyword to include my block file in my base template, so it will then be available to everything else.
{# widget_blocks.html.twig #}
{# Widgets #}
{% block my_widget %}
ABC Cookies
{% endblock %}
{# base.html.twig #}
{% use widget_blocks.html.twig %}
{{ block(my_widget.block) }}
Not exactly what I wanted, but sufficiently close.
{% render 'MyMainBundle:Default:credits' with {'arg1': $myObj } %}
Thats what I say. What's the difference between the line above or
{{ block(myObj.blockName) }}
You can register a custom filter but as far as I know it returns only string value. http://twig.sensiolabs.org/doc/advanced.html#id2

how to use php string function in twig template engine

I want to use few php string functions in twig. For e.g.
How to write below code in twing?
if (!empty($message) && substr_count($message, 'blabla')) {
....
....
}
You can't, and that's the whole point of twig.
Template should only take care of displaying data.
In that specific case, you could create a TWIG variable, and simply pass TRUE or FALSE, so that you twig code would look like:
{% if display_message %}
...
{% enfif %}
You can look at the list of expressions that are available in the twig template, strstr_count is not part of them :( http://twig.sensiolabs.org/doc/templates.html#expressions
Use filters:
{% if message is not empty and ... %}
...
{% endif %}
I think there is not a substr_count equivalent for twig, you can either make the test and pass the result to the template or create a twig extension and implement it yourself
http://twig.sensiolabs.org/documentation

Categories