2

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

1
  • Please use english in your code example or add comments to explain what the variables are for. I don't speak spanish and have no idea what all the variables mean.
    – MoritzLost
    Jun 2 '21 at 8:07
2

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.

2
  • Thanks for your response Moritz, i will check it out. Yesterday night some idea came to me: since only last category in the hierarchy will be used from the admin users to relate, they wont use for example a category level 1 that have childs options, maybe i can filter the category list to categories that DON´T HAVE DESCENDANTS, because if it has it won´t be selected, make sense? So case 1: selected category level 1: don´t have descendants. Case 2: selected category level 2: category level 1 have descendant, i must avoid it I´m checking LEAVES Jun 2 '21 at 15:02
  • You answer point me in the right direction, leaves do the job in my case, thank you! Jun 2 '21 at 15:12

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.