TransWikia.com

Get a list of last level categories in an entry - Craft CMS 3

Craft CMS Asked on June 3, 2021

I saw some similar questions, but not specific like this.

I have a list of categories, some have only 1 level, other go to 2nd level hierarchy.

Entries can have up to 4 categories related, and they can be categories of level 1 ( that don´t have childs ) or level 2.

In a list of entries ( loop ), i need to list all the related categories for each entry, but only the last level of each one, for example if is related to Real Estate -> Architecture, i don´t want to list both, just Architecture.

Any help is appreciated:

{% for item in listado %}
    {% set imagenDir = item.imagenDir[0] ?? null %}
    {% set catDir = item.categoriaDir.all() %}
    {% set zonaDir = item.zonaDir.all() %}
    {% set logoDir = item.logoDir[0] ?? null %}
    ...
    {% if catDir %}
    
    {% for item in catDir %}
    <span class="uk-label label-cat">{{ item.title }}</span>
    {% endfor %}
    
    {% endif %}

enter image description here

One Answer

I can't think of a way to do this with a single query. Category queries have a leaves method to narrow the query to leaf nodes (categories with no descendants), but that won't work in your case since you it won't give you categories that do have descendents that aren't selected on the entry. It would probably be possible to construct a query to achieve this manually, but that'll be a pretty low-level operation, so I would avoid it if it's not absolutely necessary for performance reasons.

So you'll have to manually filter the list of categories. One way I can think of to do this:

  1. Get all selected categories of the entry.
  2. Filter out all categories where one of the other categories is a descendent of itself.

Something like this should work (untested, might need some adjustments):

{% set categories = item.categoriaDir.all() %}
{% set categoryIds = categories|column('id') %}
{% set filteredCategories = categories|filter(
    cat => cat.getDescendants().id(categoryIds).exists()
) %}

Note that this suffers from the N+1 problem, so you'll want to cache this part of the template.

Correct answer by MoritzLost on June 3, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP