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


#1

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:


#2

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

#3

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.


#4

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

#5

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

Thanks!