it's now 2024 and I'm wondering what the best way to do this is.
Example Setup: News Article (with an entries field for 'Categories')
Desired result: Show 3 related (by 'category') entries, if not get any other news entry to fill up to 3.
Edit: I think I might have cracked it:
{% set relatedEntriesIds = craft.entries()
.section('news')
.relatedTo({
targetElement: entry.newsCategory,
field: 'newsCategory'
})
.id('not ' ~ entry.id)
.limit(3)
.ids()
%}
{% if relatedEntriesIds|length < 3 %}
{% set moreRelatedEntriesIds = craft.entries.section('news').id('not ' ~ entry.id).limit(3).ids() %}
{% set relatedEntriesIds = relatedEntriesIds|merge(moreRelatedEntriesIds)|unique %}
{% endif %}
{% set relatedEntries = craft.entries.id(relatedEntriesIds).limit(3).all() %}
Previous very verbose code solution:
{# First get any articles with the same category #}
{% set articleRelatedArticlesQuery = craft.entries()
.section('news')
.limit(3)
.id('not ' ~ entry.id)
.relatedTo({
targetElement: entry.newsCategory.all(),
field: 'newsCategory',
}) %}
{# Grab their IDs #}
{% set articleRelatedArticlesIDs = articleRelatedArticlesQuery.ids() ??? null %}
{# Are there less than 3? If so, we need fallback articles #}
{% if articleRelatedArticlesQuery.count() < 3 %}
{% set fallbackArticlesQuery = craft.entries()
.section('news')
.id('not ' ~ entry.id)
.limit(3)
%}
{# If there are _any_ related matching entries, make sure they are removed from the fallback query #}
{% if articleRelatedArticlesIDs %}
{# Format the string to exlude the IDs #}
{% set relatedArticleExclusionString = articleRelatedArticlesIDs|join(', not ') ??? null %}
{# Update the query #}
{% do fallbackArticlesQuery.id("and, not #{entry.id}, not #{relatedArticleExclusionString}") %}
{# Grab the Fallback IDs #}
{% set fallbackArticlesIDs = fallbackArticlesQuery.ids() ??? null %}
{# Now merge the two sets of IDs #}
{% set articleRelatedArticlesIDs = articleRelatedArticlesIDs|merge(fallbackArticlesIDs) ??? null %}
{% else %}
{% set articleRelatedArticlesIDs = fallbackArticlesQuery.ids() ??? null %}
{% endif %}
{% endif %}
{# Now grab the related articles #}
{% set articleRelatedArticles = craft.entries.section('news').limit(3).id(articleRelatedArticlesIDs).all() ??? null %}
Can anyone help me with some better code here?