how to subtract dates in twig? - twig

{%for mat in setQuery %}
{% set datePost = mat.data_criacao|date('d-m-Y') %}
{% set today = "now"|date('d-m-Y') %}
{{today- datePost}}
{% endfor %}
datePost = 17-04-2015
today = 06-05-2015
the example above returns it: -11

The issue was resolved with the following code:
{% set datePost = mat.data_criacao|date('d-m-Y') %}
{% set today = "now"|date('d-m-Y') %}
{% set difference = date(today).diff(date(datePost))%}
{% set leftDays = difference.days %}
{% if datePost == today %}
1 day
{% else %}
{{ leftDays }}
{% endif %}

You must write your custom twig extension:
You must write a twig function as described here with the following code for make diff via php function:
$calcFrom = $from;
$calcTo = $to;
$now->diff($calcFrom)->format("%a")
And make it available via a Twig extension.
If you are using symfony2 framework You can use the KnpTimeBundle
In the Twig:
This compare with the current date:
{# Returns something like "3 minutes ago" #}
{{ time_diff(form) }}
This compare with the another date:
{# Returns something like "3 minutes ago" #}
{{ time_diff(form , to ) }}
Hope this help

Related

How to render HTML to a variable

I need to render a list of HTML elements with content and put it into a variable. How can I do this efficient in twig?
e.g. I need to render the post tracking URLs from an order which can have several shippings / parcels.
{% for delivery in order.deliveries %}
{% for trackingCode in delivery.getTrackingCodes() %}
{{ trackingCode }}<br/>
{% endfor %}
{% endfor %}
Instead of printing this directly into the output I like first to put this rendered output into a variable like
{% set output = ... %}
...
{{ output }}
How can I do this in twig?
Just the concatenate the html to the output variable. Keep in mind you'll need to define to the variable outside the for-loop in order to use it outside the loop.
{% set foo = '' %}
{% for i in 1..10 %}
{% set foo = foo ~ ''~i~'' %}
{% endfor %}
{{ foo|raw }}
demo
After long search I found a better more efficient way
you can use {% set var %} with {% endset %} as a whole output block. Means the whole output will be set to the variable. This makes the life much easier and readable.
e.g.
{% set trackingText %}
{% for delivery in order.deliveries %}
{% for trackingCode in delivery.getTrackingCodes() %}
{{ trackingCode }}<br/>
{% endfor %}
{% endfor %}
{% endset %}
...
{% if trackingText|trim is not empty %}
You can track the delivery by using the following URL:<br/>
{{ trackingText }}
<br/>
{% endif %}

Twig replace part of string with chosen character

I want to replace part of string characters with asterisks in Twig.
For example:
SomePartlyVisibleStringHere
I want to change every letter after 4th in this string with asterisks, to have result like that:
Some*********************
Is it possible to do without defining new Twig helper?
You could make a macro (a function in Twig) and call it whenever you want to do this.
{% macro redact(topSecret) %}
{% set length = topSecret|length - 4 %}
{{ topSecret|slice(0, 3) }}{% for i in 0..length %}*{% endfor %}
{% endmacro %}
{# You have to import from _self if the macro is declared in the same file. #}
{% import _self as sharpie %}
{{ sharpie.redact('Top secret information') }}
{# => Top******************* #}
Example: https://twigfiddle.com/aobt8s
This worked for me:
{% set string = 'SomePartlyVisibleStringHere' %}
{% set starCount = string|length - 4 %}
{{ string[:4] }}{% for i in 1..starCount %}*{% endfor %}
If you have to do it more than once I would suggest making a custom filter, then you can just do:
{% set string = 'SomePartlyVisibleStringHere' %}
{{ string|customFilterName }}

Twig date loop each day in a period

So, here's my situation, I have a beginning date and an ending date, with Twig I want to be able to loop through all days in the so called period so that I could print out every day. Of course, that's just for understanding how to do it, the goal is to get them into a chart. Anyway, I have the following code (with what are my vars) :
{% set start_year = date(start) | date('d-m-Y') %}
{% set end_year = date(end)| date('d-m-Y') %}
{% for i in start_year..end_year %}
{{ i }}
{% endfor %}
My start var is 01-01-2003 and my end var is 10-05-2014. The values don't matter as they could change, but that's the format I have.
This actually prints out 0 1 which I don't understand at all. If anyone has an idea either how to do this or how to fix what I'm doing, it would be really nice. Thanks.
You cannot define a range of exact dates (neither as range in php) but you can create a range of seconds with step of a 24 hours second which is 86400; if you use date('U') it will convert date string to seconds since the Unix Epoch (same as Time() in php)
{% set start_date = '01-06-2014' %}
{% set end_date = '05-06-2014' %}
{% for x in range(start_date|date('U'), end_date|date('U'), 86400 ) %}
{{ x|date('d/m/Y') }}<br>
{% endfor %}
Tip
Pay attention the format of date to use - as separator not / because it will lead to totally different result
{% set pd_begdate = header_data.pd_begdate %}
{% set pd_enddate = header_data.pd_enddate ~ ' 23:59:59' %}
{% for key, count_item in range(pd_begdate|date('z'), pd_enddate|date('z'), 1)|slice(column_offset, column_count, 'preserve_keys') %}
{% set item = pd_begdate|date_modify('+'~ key ~' day') %}
<td class="tr5 td9"><p class="p9 ft0">{{ item|date("M") }}<br>{{ item|date("d") }}<br>{{ item|date("D") }}<br>{{ key + 1 }}</p></td>
{% endfor %}
This solution works for day light savings.
I had trouble with the solution when I tried to iterate over an entire year - after about 8 months, I found it would drop a day.
But based on the solution How to add n-days to twig date format within a for-loop?, I found that this would work:
{% set yearstart = "01-01-2003"|date('m-d-Y') %}
{% set eachday = "" %}
{% for i in range(0,365) %}
{% set eachday = yearstart|date_modify("+" ~ i ~ "day")|date('m-d-y') %}
{% endfor %}

for loop counter with Twig or Swig

Anyone know of a clean way to do this in Twig/Swig:
{% for(i = 0; i < 100; i++) %}
blah....
{% endfor %}
If you have a number, then you can just convert this to an array and then use Swig's standard for tag. This is simplest if you always want to 'start' the loop from 0 though.
For example:
{% set productCount = 6 %}
{% set productCountAsArray = Array(productCount) %}
{# This will run productCount times #}
{% for x, y in productCountAsArray %}
This is for number: {{ x }}
{% endfor %}
The swig docs have since (ivoba's answer) been updated and now contain special loop variables, which include loop.index:
{% for x in y %}
{% if loop.first %}<ul>{% endif %}
<li>{{ loop.index }} - {{ loop.key }}: {{ x }}</li>
{% if loop.last %}</ul>{% endif %}
{% endfor %}
http://paularmstrong.github.io/swig/docs/#tags-for
For twig its:
{% for i in 0..100 %}
* {{ i }}
{% endfor %}
From http://twig.sensiolabs.org/doc/tags/for.html
For swig the docs dont mention it yet:
https://github.com/paularmstrong/swig/blob/master/docs/tags.md#for
i cant really tell but it might be not supported in swig since its django inspired and django also seems to lack this feature nativly: https://code.djangoproject.com/ticket/5172
so i would like to pass the swig part to the next one.

Twig: in_array or similar possible within if statement?

I am using Twig as templating engine and I am really loving it. However, now I have run in a situation which definitely mustbe accomplishable in a simpler way than I have found.
What I have right now is this:
{% for myVar in someArray %}
{% set found = 0 %}
{% for id, data in someOtherArray %}
{% if id == myVar %}
{{ myVar }} exists within someOtherArray.
{% set found = 1 %}
{% endif %}
{% endfor %}
{% if found == 0 %}
{{ myVar }} doesn't exist within someOtherArray.
{% endif %}
{% endfor %}
What I am looking for is something more like this:
{% for myVar in someArray %}
{% if myVar is in_array(array_keys(someOtherArray)) %}
{{ myVar }} exists within someOtherArray.
{% else %}
{{ myVar }} doesn't exist within someOtherArray.
{% endif %}
{% endfor %}
Is there a way to accomplish this which I haven't seen yet?
If I need to create my own extension, how can I access myVar within the test function?
Thanks for your help!
You just have to change the second line of your second code-block from
{% if myVar is in_array(array_keys(someOtherArray)) %}
to
{% if myVar in someOtherArray|keys %}
in is the containment-operator and keys a filter that returns an arrays keys.
Just to clear some things up here. The answer that was accepted does not do the same as PHP in_array.
To do the same as PHP in_array use following expression:
{% if myVar in myArray %}
If you want to negate this you should use this:
{% if myVar not in myArray %}
Try this
{% if var in ['foo', 'bar', 'beer'] %}
...
{% endif %}
another example following #jake stayman:
{% for key, item in row.divs %}
{% if (key not in [1,2,9]) %} // eliminate element 1,2,9
<li>{{ item }}</li>
{% endif %}
{% endfor %}
Though The above answers are right, I found something more user-friendly approach while using ternary operator.
{{ attachment in item['Attachments'][0] ? 'y' : 'n' }}
If someone need to work through foreach then,
{% for attachment in attachments %}
{{ attachment in item['Attachments'][0] ? 'y' : 'n' }}
{% endfor %}
It should help you.
{% for user in users if user.active and user.id not 1 %}
{{ user.name }}
{% endfor %}
More info: http://twig.sensiolabs.org/doc/tags/for.html
Here's one to complete the answers with all the possibilities of Twig these days:
To achieve something like this:
{% for myVar in someArray %}
{% if myVar in someOtherArray|keys %}
{{ myVar }} exists within someOtherArray.
{% else %}
{{ myVar }} doesn't exist within someOtherArray.
{% endif %}
{% endfor %}
(https://twigfiddle.com/0b5crp)
You could also use array mapping and have the following one-liner:
(Twig >= 1.41 or >= 2.10 or any 3.x version)
{{ someArray|map(myVar => myVar ~ (myVar not in someOtherArray|keys ? ' doesn\'t') ~ ' exists within someOtherArray.')|join('\n') }}
Which outputs something quite similar.
Also see this Twig fiddle: https://twigfiddle.com/dlxj9g
{% if myVar in myArray %} without keys helps me

Resources