I need to group a set of entries alphabetically and I don't get a working and clean solution. Taking this documentation entry, I am doing it as follows:

  {% set fromAtoF = craft.entries.section('shops').type('shops').order('title').search('title:a* OR A* OR b* OR B* OR c* OR C* OR d* OR D* OR e* OR E* OR f* OR F*') %}
  {% set fromGtoL = craft.entries.section('shops').type('shops').order('title').search('title:g* OR G* OR h* OR H* OR i* OR I* OR j* OR J* OR k* OR K* OR l* OR L*') %}
  {% set fromMtoR = craft.entries.section('shops').type('shops').order('title').search('title:m* OR M* OR n* OR N* OR o* OR O* OR p* OR P* OR q* OR Q* OR r* OR R*') %}
  {% set fromStoZ = craft.entries.section('shops').type('shops').order('title').search('title:s* OR S* OR t* OR T* OR u* OR U* OR v* OR V* OR w* OR W* OR x* OR X* OR y* OR Y* OR z* OR Z*') %}
  • Problem 1: I get entries starting by 'A' like 'Amazon' in the fromStoZ group, and 'Walmart' in fromGToL...etc
  • Problem 2: It's not clean nor elegant. There must be other ways to query this but I haven't found the good one yet.

I also tried:

  {% set fromAtoF = craft.entries.section('shops').type('shops').order('title').search('title:a* OR b* OR title:c* OR title:d* OR title:e* OR title:f*') %}
  {% set fromGtoL = craft.entries.section('shops').type('shops').order('title').search('title:g* OR title:h* OR title:i* OR title:j* OR title:k* OR title:l*') %}
  {% set fromMtoR = craft.entries.section('shops').type('shops').order('title').search('title:m* OR title:n* OR title:o* OR title:p* OR title:q* OR title:r*') %}
  {% set fromStoZ = craft.entries.section('shops').type('shops').order('title').search('title:s* OR title:t* OR title:u* OR title:w* OR title:x* OR title:y* OR title:z*') %}

But neither it works; entries like 'Best Buy' and 'JC Penney' don't get into any group, but 'Best Buy2' goes correctly into fromAtoF

2 Answers 2


Not exactly sure what you are trying to do with this data, but it sounds like you could use the group filter

{% set alphaEntries = craft.entries.section('shops').type('shops').all() | group('title | slice(0, 1)') %}

{% for letter, entries in alphaEntries %}
    <h2>{{ letter }}</h2>
        {% for entry in entries %}
            <li>{{ entry.title }}</li>
        {% endfor %}
{% endfor %}
  • Hi Trevor, thanks for answering. What I need is to group shops into alphabetical groups like: From A to F: Amazon, Best Buy, Carrefour From G to L: H&M, IceLand ... etc The answer you gave me throws the error: Argument 1 passed to craft\web\twig\Extension::groupFilter() must be of the type array.. Oct 26, 2017 at 8:09
  • 1
    @RosanaRuiz in Craft 3 you need to explicitly query for the entries using all() method on the elment query object. That change should make the group filter happy!
    – carlcs
    Oct 26, 2017 at 12:36

I ended up using a combination of solutions provided:

 {% set groupedShops = craft.entries.section('shops').type('shops')
                    .order('title').all() |
                    group("title|first|upper |
                    replace('/[A-F]/', 'A to F', 1) |
                    replace('/[G-L]/', 'G to L', 1) |
                    replace('/[M-R]/', 'M to R', 1) |
                    replace('/[S-Z]/', 'S to Z', 1)") %}

Then you can do:

  {% for groupName, group in groupedShops %}
      <h1> {{ groupName }} </h1>
        {% for shop in group %}
          <li> {{ shop.title }} </li>
        {% endfor %}
  {% endfor %}

Then you have:

A to F:

  • Amazon
  • Best Buy

G to L:

  • Happy Shops
  • Hollister
  • Luxe DH


A very similar query is explained here:

How can I group a list of tags into ranges of first letters (A–E, F–J, etc.)?

Important detail pointed by @Carlcs:

In Craft 3 you need to explicitly query for the entries using all() method on the elment query object

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.