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

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>
    <ul>
        {% for entry in entries %}
            <li>{{ entry.title }}</li>
        {% endfor %}
    </ul>
{% 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.. – Rosana Ruiz Oct 26 '17 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 '17 at 12:36
up vote 3 down vote accepted

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>
      <ul>
        {% for shop in group %}
          <li> {{ shop.title }} </li>
        {% endfor %}
      </ul>
  {% endfor %}

Then you have:

A to F:

  • Amazon
  • Best Buy

G to L:

  • Happy Shops
  • Hollister
  • Luxe DH

...etc

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 acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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