I have a 2 level category system. Some have children, some do not. How can I display entries related to the last level only?

If a category has no children, it should show the entries related to the 1st level. And if there are children, it should show entries related to that child category only.

The code below currently shows both levels, which I don't want. How can I tell Craft to look for the last (bottom) level only?

{% set entries = craft.entries.relatedTo(category).order('dateYear','comp_opus','title').limit(0) %}
{% for category in craft.categories.group('compositions').relatedTo(entries) %}
    {% for entry in entries.relatedTo(category).limit(7) %}
        {# Do stuff #}
    {% endfor %}
{% endfor %}

1 Answer 1


You can loop through your top level categories and check if descendants are available. Then collect the relevant category IDs that you can later use to filter the ElementCriteriaModel.

{# Define array before loop #}
{% set bottomLevelCatIds = [] %}

{# Get top level categories only #}
{% set topLevelCats = craft.categories.group('compositions').level(1) %}

{# Loop through categories and collect relevant IDs #}
{% for topLevelCat in topLevelCats %}

    {# Check for child categories #}
    {% if craft.categories.descendantOf(topLevelCat).descendantDist('1')|length %}

        {# Merge child category IDs #}
        {% set 2ndLevelCatIds = craft.categories.descendantOf(topLevelCat).descendantDist('1').ids() %}
        {% set bottomLevelCatIds = bottomLevelCatIds|merge(2ndLevelCatIds) %}

    {% else %}

        {# Merge to level category ID #}
        {% set bottomLevelCatIds = bottomLevelCatIds|merge([topLevelCat.id]) %}

    {% endif %}

{% endfor %}

{# Get the bottom level category models #}
{% set categories = craft.categories.id(bottomLevelCatIds) %} 
  • Great, the index page works like a charm. As soon as I try to load a specific category slug Craft says:Only variables can be assigned to. Unexpected token "number" of value "2" ("name" expected). I assume I'd have to set my nav with categories IDs instead of slugs?
    – jjem
    Commented Oct 10, 2014 at 12:07
  • Sorry I don't understand what you are trying to do, @jjem. Where and how do you want to load a category slug?
    – carlcs
    Commented Oct 10, 2014 at 13:03
  • Ok I'll try to be clear. My entries are all related to one or two categories. I have 3 templates for that section: index.html (displays all entries sorted by category). entry.html (displaying entries related to a specific category chosen in the nav). detail.html (each single entry is displayed with pre/next and loops through the entries under that specific category). I'm new to Craft and a bit confused about how I should achieve this. Maybe a structure would be better.
    – jjem
    Commented Oct 10, 2014 at 13:25
  • So the index.html now works like you want and you have links to your category indexes with URLs like mysite.com/cat/mycatslug/ that should use your entry.html template, right? I'm not totally sure but if set up correctly (→ see Docs article), that template should give you access to a automatically set variable category that you can use to query your entries.
    – carlcs
    Commented Oct 10, 2014 at 14:04
  • If not try this: {% set category = craft.categories.group('compositions').slug('mycatslug').first() %} to get category model with that slug.
    – carlcs
    Commented Oct 10, 2014 at 14:07

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.