1

I want to show the entries which have same category of that entry. The entry might have multiple categories, so I want to merge the result. If there is a result, then only the whole structure will be shown. The title 'Recommended Product' should only show one time. Currently, the issue is if there are three categories, the whole structure will show three times.

{% set subcategories = craft.categories.group('prodCat').descendantOf(prodCat).level(2).relatedto(entry) %}
    {% if subcategories | length %}
        {% for subcategory in subcategories %}
            {% set relatedentry = craft.entries.section('products').relatedTo(subcategories).id('not '~entry.id).all() %}
            {% set relatedentry_count = relatedentry|length %}
            {% if relatedentry_count > 0 %}
            <div>
                <h4>Recommended Product</h4>
                <ul>
                    {% for entry in relatedentry %}
                    <li>{{entry.title}}</li>
                    {% endfor %}
                </ul>
            </div>
            {% endif %}
        {% endfor %}
    {% endif %}

Update based on the answer:

I manage to solve the issue after making some tweak of the answer given, just merge the subcategory.

{% set subcategory = craft.categories.group('prodCat').level(2).relatedto(entry) %}
{% set subcategories = subcategory|merge(subcategory) %}
    {% if subcategories | length %}
        {% set relatedentry = craft.entries.section('products').relatedTo(subcategories).id('not '~entry.id).all() %}
        {% set relatedentry_count = relatedentry|length %}
        {% if relatedentry_count > 0 %}
            <div>
                <h4>Recommended Product</h4>
                <ul>
                    {% for entry in relatedentry %}
                    <li>{{entry.title}}</li>
                    {% endfor %}
                </ul>
            </div>
        {% endif %}
    {% endif %}
1

Hopefully, I understood the question properly.

You could start by fetching your subcategories ids doing:

{% set subcategories = craft
    .categories
    .group('prodCat')
    .descendantOf(prodCat)
    .level(2)
    .relatedto(entry)
    .ids() %}

Then query your entries at once rather than looping on your subcategories:

{% set relatedEntries = craft
    .entries
    .section('products')
    .relatedTo({
        targetElement : ['or'] | merge(subcategories) 
    })
    .id('not '~entry.id)
    .all() %}

So that you only loop your relatedEntries once.

{% if relatedEntries | length %}
    <div>
        <h4>Recommended Product</h4>
        <ul>
        {% for entry in relatedEntries %}
            <li>{{entry.title}}</li>
        {% endfor %}
        </ul>
    </div>
{% endif %}

Altogether giving:

{% set subcategories = craft
    .categories()
    .group('prodCat')
    .descendantOf(prodCat)
    .level(2)
    .relatedto(entry)
    .ids() %}

{% if subcategories %}
    {% set relatedEntries = craft
    .entries()
    .section('products')
    .relatedTo({
        targetElement : ['or'] | merge(subcategories) 
    })
    .id('not '~entry.id)
    .all() %}

    {% if relatedEntries %}
        <div>
            <h4>Recommended Product</h4>
            <ul>
                {% for entry in relatedentry %}
                <li>{{entry.title}}</li>
                {% endfor %}
            </ul>
        </div>
    {% endif %}

{% endif %}

If you really need to loop the way you are already doing, you could do:

{% if loop.index == 1 %}
<div>
    <h4>Recommended Product</h4>
    <ul>
{% endif %}
        {% for entry in relatedentry %}
        <li>{{entry.title}}</li>
        {% endfor %}
{% if loop.last %}
    </ul>
</div>
{% endif %}

Which would only print your header on the first iteration and close the ul and div. It's not as nice but it should do the job!

1
  • Fetching subcategories ids doesn't work. It didn't show my entry. But the last part 'loop.index' working fine. Thanks.
    – Lee
    Apr 13 '20 at 3:41
1

You can collect the id from the previous entry, then you can exclude id in the next query. For example like this :

 {% set subcategories = craft.categories.group('prodCat').descendantOf(prodCat).level(2).relatedto(entry) %}
 {% set listId = ['not', entry.id ] %} //get id from current page id.
        {% if subcategories | length %}
            {% for subcategory in subcategories %}
                {% set relatedentry = craft.entries.section('products').relatedTo(subcategories).id(listId).all() %}
                {% set relatedentry_count = relatedentry|length %}
                {% if relatedentry_count > 0 %}
                <div>
                    <h4>Recommended Product</h4>
                    <ul>
                        {% for entry in relatedentry %}
                        {% set listId = listId|merge([entry.id]) %} // append the id from current category to the array.
                        <li>{{entry.title}}</li>
                        {% endfor %}
                    </ul>
                </div>
                {% endif %}
            {% endfor %}
        {% endif %}
1
  • This doesn't solve my issue. The title 'Recommended Product' shows twice when there are multiple categories.
    – Lee
    Apr 13 '20 at 3:34

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.