I have a channel that is essentially a list of companies participating in an event.

Within that channel is a category group of sponsorship levels.

Companies that are sponsors are assigned a category. Companies that are just participants are not categorized.

I need to output a list of companies beginning with the categorized entries, and then the rest of the uncategorized entries.

The code I'm using below outputs the categorized list, but then I'm doing another loop for all companies (not just uncategorized).

Is there a better way, where I can exclude the categorized companies from the second loop (or include the uncategorized companies in the first loop?

{% set allCompanies = shuffle(craft.entries.section('companies').all()) %}
{% set sponsorCats = craft.categories().group('sponsors').relatedTo(allCompanies) %}

{# Loop the categories #}
{% for category in sponsorCats.all() %}

    {# Get and loop through entries related to this cat #}
    {% set sponsors = craft.entries.relatedTo(category) %}

    {% for entry in sponsors.all() %}
        entry details
    {% endfor %}
{% endfor %}

{% for entry in allCompanies %}
    entry details
{% endfor %}

1 Answer 1


You could do something like this:

{# Fetch all entries in postDate and category/structure order #}
{%  set entries = craft.entries().section('companies').order('dateCreated DESC').all() | multisort(e => e.yourCategoryField.one().lft ?? 1000) %}

{# Group entries by categories and set a group name for non-categorised one #}
{% set allEntriesByCat = entries|group(e => e.yourCategoryField[0] ?? 'The non categorised one') %}

    {% for groupName, entries in allEntriesByCat  %}
        <h1 class="text-2xl">{{ groupName }}</h1>
        {% for entry in entries %}
            {{ entry.title }}<br>
        {% endfor %}
    {% endfor %}

{% endblock %}

Change yourCategoryField to your own field handle, of course. The Order of your sponsorship levels ({{ groupName }}) is the one you will define by drag/dropping in your Control Panel → Categories.

Note that this won't show an empty sponsorship level if there is no company attached to it.

  • Thanks. That's what I was looking for. If I don't need to show the group name as a header, can I eliminate one of the for loops?
    – artmem
    Feb 27, 2020 at 22:59
  • no, you'd need both loop but just don't echo {{ groupName }}. It's all on one query so the two loops don't really cost anything
    – Oli
    Feb 28, 2020 at 0:43
  • Ok, great. Thanks!
    – artmem
    Feb 28, 2020 at 4:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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