Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Twig sum row above the summerisation

Tags:

twig

symfony

I'm kinda new to twig and I know it is possible to add up values in a template and collect them in a variable. But what i actually need is to show the summerised value in the template before I sum up them. I need something like slots in the old symfony. Or in php I could do this by ob_start(). It is possible in twig somehow?

I whould like it something like this.

sum is: {{ sum }} {# obviously it is 0 right here, but i want the value from the calculation #}

{# some content.. #} 

{% set sum = 0 %}

{% for r in a.numbers}

   {% set sum = sum + r.number %}

{% endfor %}
like image 477
omgitsdrobinoha Avatar asked Sep 21 '13 14:09

omgitsdrobinoha


4 Answers

You can extend twig by adding extra filters http://symfony.com/doc/current/cookbook/templating/twig_extension.html

In your case, you can use array_sum function:

public function getFilters()
{
    return array(
        new \Twig_SimpleFilter('sum', 'array_sum'),
    );
}
like image 129
mastermed Avatar answered Dec 03 '22 15:12

mastermed


if you don't want to use the controller and want to do the summing in twig then try using the set command:

{# do loop first and assign whatever output you want to a variable #}
{% set sum = 0 %}    
{% set loopOutput %}               
    {% for r in a.numbers}            
       {% set sum = sum + r.number %}        
    {% endfor %}    
{% endset %}

 sum is: {{ sum }} 

{# some content.. #} 

{{ loopOutput }}

I assume the loop was in a specific place because it is intended to output something into the template, this allows you to rearrange the load order while still displaying as you want.

like image 38
Mortez Avatar answered Dec 03 '22 14:12

Mortez


As of Twig 1.41 and 2.10 a reduce filter was added

The reduce filter iteratively reduces a sequence or a mapping to a single value using an arrow function, so as to reduce it to a single value. The arrow function receives the return value of the previous iteration and the current value of the sequence or mapping:

{% set numbers = [1, 2, 3] %}

{{ numbers|reduce((carry, v) => carry + v) }}
{# output 6 #}

The reduce filter takes an initial value as a second argument:

{{ numbers|reduce((carry, v) => carry + v, 10) }}
{# output 16 #}

Note that the arrow function has access to the current context.

Arguments:

  • array: The sequence or mapping
  • arrow: The arrow function
  • initial: The initial value

Ref: https://twig.symfony.com/doc/2.x/filters/reduce.html

like image 25
yceruto Avatar answered Dec 03 '22 15:12

yceruto


A possible solution to this would be to use the MVC standard and let your controller do the sum calculations for you.

//In your controller file

public function yourControllerAction(){
    //how ever you define $a and $content would go here

    $sum = 0;
    foreach($objects as $a)
        $sum = 0;
        foreach($a->numbers as $r){
            $sum += $r->number;
        }
        $a->sum = $sum;
    }


    return array(
        'objects' => $objects,
        'content' => $content
    );
}

Now you have the sum variable already calculated to use in your twig file:

{# twig file #}
{% for a in objects %}
    sum is: {{ a.sum }}
    {% for number in a.numbers %}
        {{number}}
    {% endfor %}
{% endfor %}
{# some content.. #}
like image 33
Chase Avatar answered Dec 03 '22 13:12

Chase