SOLVED: Two foreach loops, one for a randomized single item and one for everything else

Hi everyone,

I have multiple items in my content file. The first item is placed in a foreach loop, the remaining items are placed in a separate foreach loop, like this:

  // First item
  <?php $items = $page -> items() -> toStructure() -> offset(0) -> limit(1);
  foreach($items as $item) : ?>

    // ...

  <?php endforeach ?>

and

  // Remaing items
  <?php $items = $page -> items() -> toStructure() -> offset(1);
  foreach($items as $item) : ?>

    // ...

  <?php endforeach ?>

This works properly in that the first item always gets placed in the first loop, but what I’d actually like is to choose a random item and place that in the first loop.

So when the page loads, item number 4 gets randomly picked, separated from the rest and placed only in the separate, first loop. When the page loads again, a different item number gets randomly picked, and so on.

Please help :slight_smile:

You can shuffle the collection and then pick the first element. A loop doesn’t really make sense for a single item:

$collection = $page->items()->toStructure()->shuffle();;
$randomItem = $collection->first(); // output without foreach loop
$otherItems = $collection->not($randomItem); // output with foreach loop

Thanks, I’ve already tried (a way more complicated and unnecessary piece of) code using “not”, but it gave back an error, as does your piece of code. When I include the third line (otherItems) I get:

Illegal offset type in unset, in /kirby/vendor/getkirby/toolkit/lib/collection.php.

  /**
   * Returns a new collection without the given element(s)
   *
   * @param args any number of keys, passed as individual arguments
   * @return Collection
   */
  public function not() {
    $collection = clone $this;
    foreach(func_get_args() as $kill) {
      unset($collection->data[$kill]);
    }
    return $collection;
  }

I’m on 2.5.12 in local environment.

Yeah, I wasn’t sure myself if that works or not :wink: I’ll check.

Ok, that was a bit stupid of me, use:

$otherItems = $collection->offset(1); // output with foreach loop

Yes. Of course, that makes sense. Guess I’ve been staring at my screen too long.

Thanks!