# Repeat escaped foreach until count is met

**URL:** <https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249>\
**Category:** Questions\
**Tags:** v3\
**Created:** [September 3, 2020, 3:45am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249 "2020-09-03T03:45:26Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![PaulNT](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/paulnt/32/8977_2.png) [@PaulNT](https://forum.getkirby.com/u/PaulNT)\
**Post date:** [September 3, 2020, 3:45am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/1 "2020-09-03T03:45:26Z")

</div>

Hi there,

I’m trying to repeat a foreach loop from a files field until the count meets at least 10 images. The foreach needs to escape so i can use thumbs and srcset.

For example, if the user has uploaded 5 images it’ll run twice, if 2 images then 5 times, if 10 images then once, if 11 then it’ll load the first 10.

I think i’m completely barking down the wrong tree but so far i’ve been pulling range to repeat the list then was thinking to cull it down to 10 images - is this the right way to go around this?

Any help is much appreciated!! Thanks.

```
<?php $projectimg = $project->imagery()->toFiles();
foreach (range(1,10) as $i): ?>
<?php foreach($projectimg as $file): ?>
<img class="lazy" src="<?= $file->thumb('standard')->url() ?>" srcset="<?= $file->thumb('standard')->url() ?>" data-src="<?= $file->url() ?>" data-srcset="<?= $file->srcset([720, 1280, 1920]) ?>" />
<?php endforeach ?>
<?php endforeach ?>

```

---

<div class="post-metadata">

**Author:** ![sebastiangreger](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/sebastiangreger/32/16176_2.png) [@sebastiangreger](https://forum.getkirby.com/u/sebastiangreger)\
**Post date:** [September 3, 2020, 6:32am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/2 "2020-09-03T06:32:47Z")

</div>

One of probably many ways to do this:

```auto
<?php $i = 0;
foreach($project->imagery()->toFiles() as $file): ?>
<img class="lazy" src="<?= $file->thumb('standard')->url() ?>" srcset="<?= $file->thumb('standard')->url() ?>" data-src="<?= $file->url() ?>" data-srcset="<?= $file->srcset([720, 1280, 1920]) ?>" />
<?php $i++;
if($i == 10) break;
endforeach; ?>

```

---

<div class="post-metadata">

**Author:** ![PaulNT](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/paulnt/32/8977_2.png) [@PaulNT](https://forum.getkirby.com/u/PaulNT)\
**Post date:** [September 3, 2020, 9:11pm UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/3 "2020-09-03T21:11:59Z")

</div>

Thanks for your response Sebastian.

This however cuts off anything over 10 but it doesn’t repeat the loop if theres less than 10 objects in the field. I need it to repeat it until theres 10 iterations of the objects.

So if the user only uploads say 2 images into the field, it will repeat it 5 times to make sure theres 10 images being rendered.

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [September 3, 2020, 9:37pm UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/4 "2020-09-03T21:37:30Z")

</div>

Something like this (not tested);

```auto
$images = $project->imagery()->toFiles();
$count = $images->count();
$repeat = ceil(10/$count);
$imageArray = array_merge(...array_fill(0, $repeat, $images->toArray));
$i = 0 ;
while ( $i <= 10 ) {
  dump( $imageArray[$i]);
  $i++
}

```

You could prepend a test that if you already have enough images, you don’t have to do this array stuff…

---

<div class="post-metadata">

**Author:** ![sebastiangreger](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/sebastiangreger/32/16176_2.png) [@sebastiangreger](https://forum.getkirby.com/u/sebastiangreger)\
**Post date:** [September 4, 2020, 5:22am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/5 "2020-09-04T05:22:01Z")

</div>

Sorry Paul, I indeed missed that aspect of your question! I like the Array approach above, yet here’s how I would probably have approached this without Sonja’s input (also untested, extending on my earlier suggestion of utilizing the `break` statement):

```auto
<?php
$projectimg = $project->imagery()->toFiles();
$i = 0;
while ($i < 10):
    foreach($projectimg as $file): ?>
        <img class="lazy" src="<?= $file->thumb('standard')->url() ?>" srcset="<?= $file->thumb('standard')->url() ?>" data-src="<?= $file->url() ?>" data-srcset="<?= $file->srcset([720, 1280, 1920]) ?>" alt="" />
        <?php $i++;
        if($i == 10)
            break;
    endforeach;
endwhile; ?>

```

The `while` loop restarts as long as `$i` has not reached 10 yet, then the `foreach` loop gets executed on every iteration of the `while` loop. In case we reach 10 within the `foreach` loop, it is interrupted by `break` and then the `while` loop will be exited because its condition is no longer true.

…that said, I’d personally drop my own approach and go with @texnixe’s suggestion.

PS: I took the freedom to add the missing `alt` attribute to your `<img>` tag for accessibility 😉

---

<div class="post-metadata">

**Author:** ![PaulNT](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/paulnt/32/8977_2.png) [@PaulNT](https://forum.getkirby.com/u/PaulNT)\
**Post date:** [September 6, 2020, 10:11pm UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/6 "2020-09-06T22:11:53Z")

</div>

Hey,

Thank you for your answers, very insightful.

I haven’t dealt with arrays much so stumbling my way through it and don’t quite get the result i’m after. Probably doing this completely wrong but the last result I got loaded the src with 10 iterations of the same URL wrapped in `<pre>` tags.

Very lost 🥴 This is where I am at…

```
<?php
$images = $project->imagery()->toFiles();
if($images->isNotEmpty()): ?>
<img src="<?php 
$count = $images->count();
$repeat = ceil(10/$count);
$imageArray = array_fill(0, $repeat, $images->toArray());
$merged = array_merge($imageArray);
$marray = array_values($merged)[0];
$i = 0 ;
while ($i <= 4) {
  $m2 = array_values($marray)[$i];
  print($m2['url']);
  $i++;
}
 ?>" alt="<?= $project->title() ?>"><?php endif ?>
```

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [September 7, 2020, 1:44am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/7 "2020-09-07T01:44:29Z")

</div>

```auto
<?php

// Get a max of 10 files
// Convert collection to array to reset item keys
$images = $project->imagery()->toFiles()->limit(10)->values();

// Add items until there are at least 10 of them
while (count($images) < 10) {
  array_push($images, ...$images);
}

// Ensure there are 10 items in the end
$images = array_slice($images, 0, 10);

?>

<?php foreach ($images as $image) : ?>
  <img class="lazy" src="<?= $image->thumb('standard')->url() ?>" srcset="<?= $image->thumb('standard')->url() ?>" data-src="<?= $image->url() ?>" data-srcset="<?= $image->srcset([720, 1280, 1920]) ?>" alt="" />
<?php endforeach ?>

```

_\* Requires PHP 7.4 (for earlier versions [see](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/10))_

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [September 7, 2020, 1:55am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/8 "2020-09-07T01:55:07Z")

</div>

Another alternative:

```diff
// ...

// Add items until there are at least 10 of them
while (count($images) < 10) {
- array_push($images, ...$images);
+ array_push($images, ...array_slice($images, 0, 10 - count($images)));
}
- 
- // Ensure there are 10 items in the end
- $images = array_slice($images, 0, 10);

```

---

<div class="post-metadata">

**Author:** ![PaulNT](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/paulnt/32/8977_2.png) [@PaulNT](https://forum.getkirby.com/u/PaulNT)\
**Post date:** [September 7, 2020, 2:04am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/9 "2020-09-07T02:04:00Z")

</div>

Thanks for your suggestion but both these give me a 500 error and the page times out with:

> Maximum execution time of 30 seconds exceeded

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [September 7, 2020, 6:31am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/10 "2020-09-07T06:31:09Z")

</div>

The PHP spread operator requires PHP 7.4.

You can replace it with `array_merge` if PHP 7.4 is not an option for you:

```diff
- array_push($images, ...array_slice($images, 0, 10 - count($images)));
+ $images = array_merge($images, array_slice($images, 0, 10 - count($images)));

```

---

<div class="post-metadata">

**Author:** ![PaulNT](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/paulnt/32/8977_2.png) [@PaulNT](https://forum.getkirby.com/u/PaulNT)\
**Post date:** [September 7, 2020, 11:18pm UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/11 "2020-09-07T23:18:59Z")

</div>

Hi Pedro, running 7.4.2 and still timing out.

Its wrapped in a foreach element - is this a potential cause?

```
<ul>
        <?php foreach($page->children()->listed() as $project): ?>
        <li>
            <button onclick="projectop(this)">
                <?= $project->title() ?>
                <div class="imagecontainer">
                    <div class="images">
                        <div class="ticker" data-ticker>
                        <?php

// Get a max of 10 files
// Convert collection to array to reset item keys
$images = $project->imagery()->toFiles()->limit(10)->values();

// Add items until there are at least 10 of them
while (count($images) < 10) {
  array_push($images, ...$images);
}

// Ensure there are 10 items in the end
$images = array_slice($images, 0, 10);

?>

<?php foreach ($images as $image) : ?>
  <img class="lazy" src="<?= $image->thumb('standard')->url() ?>" srcset="<?= $image->thumb('standard')->url() ?>" data-src="<?= $image->url() ?>" data-srcset="<?= $image->srcset([720, 1280, 1920]) ?>" alt="" />
<?php endforeach ?>
                        </div>

                    </div>
                </div>
            </button>
          </li>
</ul>
```

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [September 8, 2020, 1:32am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/12 "2020-09-08T01:32:26Z")

</div>

You need to end the first `foreach`:

```diff
        </li>
+ <?php endforeach ?>
</ul>

```

You should be getting an error message about this. If you are not, enable the `debug` [option](https://getkirby.com/docs/reference/system/options/debug) in Kirby.

Another tip, getting into the habit of properly indenting your code helps prevent this kind of bug 😉

---

<div class="post-metadata">

**Author:** ![PaulNT](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/paulnt/32/8977_2.png) [@PaulNT](https://forum.getkirby.com/u/PaulNT)\
**Post date:** [September 8, 2020, 1:52am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/13 "2020-09-08T01:52:20Z")

</div>

Sorry that was in, I was paraphrasing the closing as there are other parts to the loop that are irrelevant to this.

That doesnt resolve the error.

 ![Screen Shot 2020-09-08 at 1.50.54 PM](https://europe1.discourse-cdn.com/flex017/uploads/getkirby/original/2X/a/ab03b3c5f62024323a4c7584a39d7f53d5a9b92f.png)

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [September 8, 2020, 2:33am UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/14 "2020-09-08T02:33:00Z")

</div>

Try to locate this error log, it will point you in the right direction.

My solution should work, at least it does in a project of mine I tested it on.

 ![Screen Shot 2020-09-07 at 23.30.28](https://europe1.discourse-cdn.com/flex017/uploads/getkirby/original/2X/a/ad560f589e134199c6dadf9f6803be168b327c7a.png)

 ![Screen Shot 2020-09-07 at 23.31.09](https://europe1.discourse-cdn.com/flex017/uploads/getkirby/original/2X/0/07d8ebdb6f4711bb01f928ca124dac3b8ddcc096.png)

_\* The `array_map` line is not part of the solution, it just outputs the result in a way I can easily verify it._

---

<div class="post-metadata">

**Author:** ![PaulNT](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/paulnt/32/8977_2.png) [@PaulNT](https://forum.getkirby.com/u/PaulNT)\
**Post date:** [September 8, 2020, 8:49pm UTC](https://forum.getkirby.com/t/repeat-escaped-foreach-until-count-is-met/19249/15 "2020-09-08T20:49:45Z")

</div>

No error log is being generated and its still not working.  
Completely crashes the page with a 500 error so it doesn’t even hit the debug screen which is turned on in config.
