Several projects I work on use the Twig templating system to separate the look of a site from the backend logic. One change I was asked for recently was to display a list of products in descending order of price.
There are three ways I could do this:
- Sort the products when they are fetched from the database, e.g. ORDER BY price DESC. The issue with this is that the list of products is used in several places in the code, and I didn’t want to re-order every instance.
- Create a separate product list ordered by price. Some templates use the product list multiple times though, so I would need to create multiple product lists where the only difference was the ordering.
- Sort the products in the template.
I decided to sort the products in the template, as this was a decision about how to display the prices rather than how to process them.
If the product list is already an array, then sorting it before use is very easy in Twig:
{% for product in products|sort((a, b) => b.price <=> a.price) %} <li>{{ product.name }} costs {{ product.price }}</li> {% endfor %}
The sort function needs an ordering, and in this case it says ‘for any two items, a and b, order b before a if b.price is greater than or equal to a.price‘.
If I wanted products in ascending order of price, I would instead do:
{% for product in products|sort((a, b) => a.price <=> b.price) %} <li>{{ product.name }} costs {{ product.price }}</li> {% endfor %}
This would allow me to show products in ascending and descending order of price, in the same template, without having to rewrite any of the processing code.