Error loading random image from specific file selector field on random page

Hi,

I’m following Kirby’s random content guide to fetch an array of 3 random images from random pages, however I’d like for the images to be from a specific file selector field instead of all images on that page.

<?php
    $references = page('exhibitions')
      ->children()
      ->references()
      ->shuffle()
      ->limit(3)
      ->toFiles();
    foreach($references as $reference): ?>
      <li>
        <img src="<?= $reference->url() ?>">
      </li>
    <?php endforeach ?>

In my code “references()” is the image selector field, which I’m using in place of all “images()”. For some reason this gives me an error, though when I use “images()” without the toFiles() method it works fine. I have images uploaded to the specified image selector field too, so that shouldn’t be an issue.

Any help would be enormously appreciated!

Update: Is the problem actually with trying to fetch images from a files field on multiple pages?

I tried the following and it worked:

<?php
    $references = page('exhibitions')
      ->children()
      ->shuffle()
      ->first()
      ->references()->toFiles()
      ->shuffle()
      ->limit(3);
      foreach($references as $reference): ?>
        <li>
          <?= $reference->url() ?>
        </li>
      <?php endforeach ?>

But ideally I could get random images from the “references” field on all children pages of “exhibitions”…

You cannot call a field on a collection of pages.

There are different ways to achieve this, either looping through the pages or filtering the files. Maybe the last example is the best.

<?php
$files       = new Files();
$exhibitions = page('exhibitions')->children();
foreach ($exhibitions as $exhibition) {
  $files->add( $exhibition->references()->toFiles());
}

$files = $files->shuffle()->limit(3);
foreach($files as $reference): ?>
  <li>
    <img src="<?= $reference->url() ?>">
  </li>
<?php endforeach ?>

Alternatively:

$files = new Files();
$fields = page('exhibitions')->children()->pluck('references');
foreach ($fields as $field) {
  $files->add($field->toFiles());
}
dump($files);
// then as above

Or (same as first example, only using map() instead of the foreach loop):

$files = new Files();
page('exhibitions')->children()->map(fn ($child) => $files->add($child->references()->toFiles()));
$files = $files->shuffle()->limit(3);

In all three examples, we instantiate a new Files object and then loop through the pages/fields to add the files from the references field to this object.

Or filtering the files by whether or not they are contained in the field:

$files = page('exhibitions')->children()->files()->filter(fn ($file) => $file->parent()->references()->toFiles()->has($file))->shuffle()->limit(3);

If the files in your references field have a template assigned, you could first filter by that template:

$files = page('exhibitions')->children()->files()->template('yourTemplateName')->filter(fn ($file) => $file->parent()->references()->toFiles()->has($file))->shuffle()->limit(3);

Thanks @texnixe ! I had a feeling I didn’t quite understand fetching content from page collections yet; your thorough explanation with various approaches was really helpful. I ended up using the third example and it worked beautifully :slight_smile: