I need to set some conditions in twig, so i have this:
{% if app.session.get('campaignVersion') is not null and is not '4.4d'}
...
{% elseif app.session.get('campaignVersion') is null or '4.4d' %}
...
{% endif %}
But i have errors with syntax and logic, maybe it must have an standard operator such as !=, what i'm doing wrong? Thx for help.
Twig is not a human language interpreter :-)
Twig is not able to implicitly know who is the subject in and is not '4.4d'.
Try with:
{% if app.session.get('campaignVersion') is not null and app.session.get('campaignVersion') != '4.4d' %}
Or for better readibility:
{% if app.session.get('campaignVersion') not in [null, '4.4d'] %}
A % is missing at the end of the first line
Related
I have a twig template where I would like to test if an item begins with a certain value
{% if item.ContentTypeId == '0x0120' %}
<td><a href='?parentId={{ item.Id }}'>{{ item.BaseName }}</a><br /></td>
{% else %}
<td><a href='?{{ item.UrlPrefix }}'>{{ item.LinkFilename }}</a></td>
{% endif %}
The 0x0120 can look like that or be more complex like this 0x0120D52000D430D2B0D8DD6F4BBB16123680E4F78700654036413B65C740B168E780DA0FB4BX. The only thing I want to do is to ensure that it starts with the 0x0120.
The ideal solution would be to solve this by using regex but I'm not aware if Twig supports this?
Thanks
You can do that directly in Twig now:
{% if 'World' starts with 'F' %}
{% endif %}
"Ends with" is also supported:
{% if 'Hello' ends with 'n' %}
{% endif %}
Other handy keywords also exist:
Complex string comparisons:
{% if phone matches '{^[\\d\\.]+$}' %} {% endif %}
(Note: double backslashes are converted to one backslash by twig)
String contains:
{{ 'cd' in 'abcde' }}
{{ 1 in [1, 2, 3] }}
See more information here: http://twig.sensiolabs.org/doc/templates.html#comparisons
Yes, Twig supports regular expressions in comparisons: http://twig.sensiolabs.org/doc/templates.html#comparisons
In your case it would be:
{% if item.ContentTypeId matches '/^0x0120.*/' %}
...
{% else %}
...
{% endif %}
You can just use the slice filter. Simply do:
{% if item.ContentTypeId[:6] == '0x0120' %}
{% endif %}
You can always make your own filter that performs the necessary comparison.
As per the docs:
When called by Twig, the PHP callable receives the left side of the filter (before the pipe |) as the first argument and the extra arguments passed to the filter (within parentheses ()) as extra arguments.
So here is a modified example.
Creating a filter is as simple as associating a name with a PHP
callable:
// an anonymous function
$filter = new Twig_SimpleFilter('compareBeginning', function ($longString, $startsWith) {
/* do your work here */
});
Then, add the filter to your Twig environment:
$twig = new Twig_Environment($loader);
$twig->addFilter($filter);
And here is how to use it in a template:
{% if item.ContentTypeId | compareBeginning('0x0120') == true %}
{# not sure of the precedence of | and == above, may need parentheses #}
I'm not a PHP guy, so I don't know how PHP does regexes, but the anonymous function above is designed to return true if $longString begins with $startsWith. I'm sure you'll find that trivial to implement.
Here's the PHP code:
if ($var===0) {do something}
It "does something" only when $var is actually 0 (and if $var is not set, it doesn't work, so everything is OK).
However, Twig doesn't support === operator, and if I write:
{% if var==0 %}do something{% endif %}
it "does something" all the time (even when $var is not set). In order to fix it, I wrote such a code:
{% if var matches 0 %}do something{% endif %}
Is it a proper way to do === comparison in Twig, or I did something wrong here? If it's wrong, how should it be fixed?
You need to use same as in Twig for === comparisons:
{% set var1=0 %}
{% set var2='0' %}
{% if var1 is same as( 0 ) %}
var1 is 0.
{% else %}
var1 is not zero.
{% endif %}
{% if var2 is same as( 0 ) %}
var2 is 0.
{% else %}
var2 is not 0.
{% endif %}
{% if var2 is same as( '0' ) %}
var2 is '0'.
{% else %}
var2 is not '0'.
{% endif %}
Here is a twigfiddle showing it in operation:
https://twigfiddle.com/k09myb
Here is the documentation for same as also stating that it is equivalent to ===. Hope that helps you!
Twig doesn't have === but it has same as instead. See: https://twig.sensiolabs.org/doc/2.x/tests/sameas.html
So you could write:
{% if var is same as(0) %}do something{% endif %}
Eventually, you can use is defined to check whether the variable is set.
Are there any nice ways to use while and repeat loops in Twig? It is such a simple task, but without macros I can't find anything nice and simple.
At least do an infinite cycle and then break it in a condition?
EDIT:
I mean something like
do {
// loop code
} while (condition)
or
while (condition) {
// loop code
}
Edit 2:
Looks like it is not supported natively by twig same reason as it is not supported neither continue; or break; statements.
https://github.com/twigphp/Twig/issues/654
You can emulate it with for ... in ... if by using a sufficiently-high loop limit (10000?)
while
PHP:
$precondition = true;
while ($precondition) {
$precondition = false;
}
Twig:
{% set precondition = true %}
{% for i in 0..10000 if precondition %}
{% set precondition = false %}
{% endfor %}
do while
PHP:
do {
$condition = false;
} while ($condition)
Twig:
{% set condition = true %} {# you still need this to enter the loop#}
{% for i in 0..10000 if condition %}
{% set condition = false %}
{% endfor %}
I was able to implement a simple for loop in twig. So the following php statement:
for ($x = 0; $x <= 10; $x++) {
echo "The number is: $x <br>";
}
when translated to twig is:
{% for i in 0..10 %}
* {{ i }}
{% endfor %}
It's not a while loop but a potential workaround. The best suggestion is to leave business logic like this out of the template layer.
In a nutshell: no. This functionality implies advanced logic, which should be in your business logic, not in the template layer. It's a prime example of the separation of concerns in MVC.
Twig supports for-loops completely, which should suffice if you code correctly - being that complex conditional decisions on which data to display are taken in the business logic where they belong, which then pass a resulting array 'ready to render' to the templates. Twig then supports all nice features only needed for rendering.
This is possible, but a little bit complicated.
You can use {% include ... %} to process nested arrays, which from the comments I read is what you need to do.
Consider the following code:
nested_array_display.html
<ul>
{% for key, val in arr %}
<li>
{{ key }}:
{% if val is iterable %}
{% include 'nested_array_display.html' %}
{% else %}
{{ val }}
{% endif %}
</li>
{% endfor %}
</ul>
Warning with the top solution with "high loop limit" : the loop doesn't break when the condition returns false, it just doesn't enter the loop. So the loop runs up to the high indice
First of all, I know that the logic should be in the controller and not in the view and I keep it that way.
But in this particular situation I need to use preg_match within a ternary operation to set the css class of a div.
Example:
{% for list in lists %}
<div class="{{ (preg_match(list.a, b))>0 ? something : else }}"...>...</div>
{% endfor %}
How can I achieve the (preg_match(list.a,b))>0 condition in twig?
Thanks in advance
For those who came here from Google search results (like me).
There's containment operator that allows you to do something like this:
{{ 'cd' in 'abcde' }} {# returns true #}
You can't use preg_match() directly but there are ways to accomplish it:
if your list is an entity, add a method matches(): {{ (list.matches(b)) ? something : else }}
you could create a custom Twig extension function that uses preg_match() internally http://symfony.com/doc/master/cookbook/templating/twig_extension.html
Expanding from Serge's comment and is the correct answer.
In my example my string is "Message Taken - 12456756". I can then use |split to convert it into an array and use |replace to get ride of white space.
{% set mt = 'Message Taken' in d.note %}
{% if mt == true %}
{#.. you can then do something that is true#}
{% set mt_array = d.note|split('-') %}
{{ mt_array[0] }} | {{ mt_array[1]|replace({' ' : ''}) }}
{% endif %}
This would output my string but I now control two parts instead of 1.
I'm trying to do an if statement with data passed to the twig file from the controller. Below is a line from the controller:
return $this->redirect($this->generateUrl('homepage', array('user' => $user, 'contact' => $contact)));
My goal is to do an if statement with the variable 'contact'. I checked the twig reference and it shows how to do an if statement but that would not work with 'contact'. Below is the code I tried, can somebody tell me what I'm doing wrong?
{% if {{ contact.id }} > 0 %}
{{ contact.addrLineOne }}
{% else %}
--
{% endif %}
You're almost there, just a small syntax modification will make your code working!
{% if contact.id > 0 %}
{{ contact.addrLineOne }}
{% else %}
--
{% endif %}
In Twig, curly braces means that you want to print the value of a variable or an expression. So you're statement in PHP would look like this :
if ((echo contact[id]) > 0)
echo contact[addrLineOne]; // or contact->addrLineOne() according to the context
else
--