2

I am having entries in a Craft channel-section. Each entry has the field "type" with one category filled. I need to iterate through the entries and count the amount of each category.

Example:

Entry 1, Category: One
Entry 2, Category: One
Entry 3, Category: Two

Produces something like

One: 2, Two: 1

So I know which category is used how often. In any language I would use a key/value set and just increment the amount each time I find the specific category, but that seems to be impossible with Twig in Craft.

How can I achieve that?

3

Before we proceed, let me say that whilst the following will work, I personally think this is a poor use of Twig.

It's far better to collate this information in a simple plugin, rather than jumping through such hoops in your templates.

Caveats dispensed with, here you go:

{% set criteria = {
    section: 'exampleSection',
    limit: 20,
    with: ['categoryFieldHandle']
} %}

{% set categories = {} %}
{% set entries = craft.entries(criteria).find() %}

{% for entry in entries %}
    {% set entryCategories = entry.categoryFieldHandle %}
    {% if entryCategories|length %}
        {% for entryCategory in entryCategories %}
            {% set categorySlug = entryCategory.slug %}

            {% if categories[categorySlug] is not defined %}
                {% set categories = categories|merge({
                    (categorySlug): {
                        count: 0,
                        category: entryCategory
                    }
                }) %}
            {% endif %}

            {% set categoryCount = attribute(categories, categorySlug)['count'] + 1 %}

            {% set categories = categories|merge({
                (categorySlug): {
                    count: categoryCount,
                    category: entryCategory
                }
            }) %}
        {% endfor %}
    {% endif %}
{% endfor %}

{% if categories|length %}
    <h2>Category Counts</h2>
    <ul>
        {% for categoryKey, categoryInfo in categories %}
            <li>{{ categoryInfo.category.title }}: {{ categoryInfo.count }}</li>
        {% endfor %}
    </ul>
{% endif %}

Note that we're eager loading the categories. Otherwise, we'll end up with N+1 queries.

  • Thanks a lot! I will look into plugins then and start with this – mstoldt Feb 20 '17 at 20:12
  • Sounds good. You can translate the above approach to PHP pretty easily. – Stephen Lewis Feb 20 '17 at 21:19

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.