I need to get a list of variants from multiple products, but in a way that allows us to show the results in Craft's handy {% paginate %} tags.

So far we have this less-than-appealing markup:

{% set firstProduct  = craft.products.relatedTo(category).one() %}
{% set results = craft.variants({product: firstProduct}) %}

{% set products  = craft.products.relatedTo(category).all() %}

{% for product in products %}
    {% set results = results|merge(craft.variants({product: product})) %}
{% endfor %}

However, because we're using merge it's turning our ElementCriteriaModel into an Array. Is there a way to use the {{ craft.variants({product: product}) }} tag and pass it multiple products?

(Craft3 and Commerce2)


EDIT: Final markup that ended up working:

{# All products within this category #}
{% set products = craft.products.relatedTo(category).all() %}

{# Empty variant id array #}
{% set variantIds = [] %}

{# Populating variant id array #}
{% for product in products %}
    {% set variantIds = variantIds|merge(craft.variants({product: product}).ids()) %}
{% endfor %}

{# Get all variants from the variant id array #}
{% set results = craft.variants.id(variantIds).orderBy('title asc') %}

1 Answer 1


The "variant" method can receive multiple ids using the following: craft.variants().id([1,2,3]).

Following that, you can easily populate an array while looping through your (specific) products, and then use that array to fetch the variants.

Official documentation

  • This helped me understand it. Thanks! See my answer for the final markup. :)
    – Jay
    Jan 15, 2019 at 15:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.