'Twig sort array of objects by field

I have entity with fields:

User

  • name
  • lastname
  • age

and few more. Im sending to Twig array with objects user.

In twig display users in table:

 {% for user in users %}
     <td>{{ user.name }}<td> <td>{{ user.lastname}}<td> <td>{{ user.age}}<td>
 {% endfor %}

How can I sort users via name or lastname etc. in Twig. I want to create sortable table.



Solution 1:[1]

Starting with Twig 2.12 (released on October 5, 2019) you can use the sort filter with an arrow function in the arrow argument.

For example, to order by name:

{% for user in users|sort((a, b) => a.name <=> b.name) %}
    <td>{{ user.name }}</td> <td>{{ user.lastname}}</td> <td>{{ user.age}}</td>
{% endfor %}

Twig docs: https://twig.symfony.com/doc/2.x/filters/sort.html

Solution 2:[2]

Yes, You can add custom filter:

{% for user in users|usort %}
    ...
{% endfor %}

and then add Extension/new filter to Twig:

new \Twig_SimpleFilter('usort', array($this, 'usortFilter'))

public function usortFilter($item){
    usort($item, function ($item1, $item2) {
        if ($item1['orderNo'] == $item2['orderNo']) return 0;
        return $item1['orderNo'] < $item2['orderNo'] ? -1 : 1;
    });

    return $item;
}

Solution 3:[3]

Sorting in reverse order:

{% for user in users|sort|reverse %}
    ...
{% endfor %}

sort and revers are combinable.

Solution 4:[4]

I'm using Timber for Wordpress which still uses Twig 1+, so I couldn't use the arrow argument. I just created a filter like this using PHP’s usort function:

// sort an array of objects by parameter
$twig->addFilter( new Twig_SimpleFilter( 'sort_by_key', 
    function ( $array, $key, $order = 'asc', $type = 'string' ) {
        usort( $array, function($a, $b) use ($key, $order, $type) {
        $a = $a[$key]; $b = $b[$key];
        if( $type === 'date' ) {
            $a = strtotime( $a );
            $b = strtotime( $b );
        }
        if( $a == $b ) {
            return 0;
        }
        switch( $order ) {
            case 'desc' : case  'DESC' :
                return $a < $b ?  1 : -1;
                break;
            default :
                return $a < $b ?  -1 : 1;
        }
        }  );
        return $array;
    }));

And then in my twig template:

    {% set array = myArrayOfObjects | sort_by_key('date', 'desc', 'date') %}

Works well with the Advanced Custom Fields repeater field.

Solution 5:[5]

With new version twig you can sort by colonne

{% set fruits = [
{ name: 'Apples', quantity: 5 },
{ name: 'Oranges', quantity: 2 },
{ name: 'Grapes', quantity: 4 },] %}
{% for fruit in fruits|sort((a, b) => a.quantity <=> b.quantity)|column('name') %}
    {{ fruit }}
{% endfor %}

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

Solution 6:[6]

You must do this in your model using an "Order by" clause. However, if you want to have a table that can be sorted dynamically, you should watch about the jQuery tablesorter plugin (or equivalent if you do not want to use jQuery).

http://tablesorter.com/docs/

Solution 7:[7]

For those working with Collections in Grav, you can simply do this:

{% for user in users.order("name", "asc") %}
     ...
{% endfor %}

Of course, name can be any property of the given object and asc can alternatively be desc.

This also works with dot-concatenated properties:

{% for child in page.children.order("page.headers.foo.bar", "desc") %}

Solution 8:[8]

Before Twig 2.12 It was not possible out of the box to order by specific field. Update your twig, or you could write a custom twig extension which does what you need. See @cgaldiolo and @unbreak answers.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 unbreak
Solution 3 BenS.
Solution 4
Solution 5 Lamri Djamal
Solution 6 Devatoria
Solution 7
Solution 8