2

I have a main product image and 4 thumbnails. Main product image is a lightswitch which is named productMainImage.

Here below i first iterate for the main image (which lightswitch is on) and than i make a second for loop for 4 thumbnails.

My problem is i don't like this code and it seems inefficient. I have to go out and go in for the loop because of my html stucture.

Can anyone help me to write this better?

<!-- Product Image -->
<div class="small-12 medium-5 column">
  <div class="row">
    {% for image in product.productImages %}
      {% if image.productMainImage %}
        <div class="small-12 column">
          <a class="fancybox" rel="gallery1" href="{{image.getUrl()}}"><img src="{{image.getUrl('productPageMainImage')}}" alt=""></a>
        </div>
        {% endif %}
    {% endfor %}
    <div class="small-12 column">
      <div class="row small-collapse medium-uncollapse">
        {% for image in product.productImages %}
        <div class="small-3 column">
          <a class="fancybox" rel="gallery1" href="{{image.getUrl()}}"><img src="{{image.getUrl('productPageThumbnail')}}" alt=""></a>
        </div>
        {% endfor %}
      </div>
    </div>
  </div>
</div><!-- Product Image END -->
3

One way to do this is to query for the images once, and sort them into two different arrays. This uses twig's merge filter, which is the way to add things to an array in twig.

{% set mainImages = [] %}
{% set otherImages = [] %}

{% for image in product.productImages %}
  {% if image.productMainImage %}
    {% set mainImages = mainImages | merge([image]) %}
  {% else %}
    {% set otherImages = otherImages | merge([image]) %}
  {% endif %}
{% endfor %}

Then you can loop over the mainImages array to get the images with the lightswitch on, and the otherImages array to get the other images.

You will have three for loops, but only one database query.

2

Actually, your code doesn't look inefficient to me. While Marion's solution is cool, I don't think it'll impact your performance. Craft is pretty smart about caching the results of database queries as it goes. So you could call 100 different loops thru product.productImages and not incur a performance penalty. Yay Craft!

Try it yourself in a test template:

{% for i in 1..100 %}
  {% for image in product.productImages %}
    <div class="small-3 column">
      <a class="fancybox" rel="gallery1" href="{{image.getUrl()}}"><img src="{{image.getUrl('productPageThumbnail')}}" alt=""></a>
    </div>
  {% endfor %}
{% endfor %}

The only thing I see that would simplify your code a bit would be to include your conditional statement in the first for loop statement as a filter.

{% for image in product.productImages if image.productMainImage %}
  <div class="small-12 column">
    <a class="fancybox" rel="gallery1" href="{{image.getUrl()}}"><img src="{{image.getUrl('productPageMainImage')}}" alt=""></a>
  </div>
{% endfor %}
1
  • Thanks Alex, as a matter of fact, i changed my approach. Rather than using lightswitch for a main image, i use first() and then use offset(1) for the other images. But thanks for example, i will keep in my mind.
    – orionlogic
    Feb 22 '17 at 10:58

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.