Get random content outside of foreach loop

Now obviously this code is broken, but it is almost my desired HTML output. I want to be able to inject random content in a fixed HTML structure that doesn’t require a foreach loop. I achieved this inside a foreach loop but how would I achieve it without one? Do I need to somehow print the content to an array or something?

<?php $projects = page('projects')->children()->visible()->shuffle();  ?>

<div class="container-fluid">
	<div class="col12 col4--md">
		<a href="<?= $projects->url() ?>" class="col12">
			<img src="<?= $projects->url() ?>" alt="Thumbnail for <?= $projects->title() ?>" />
		</a>
		<a href="<?= $projects->url() ?>" class="col12">
			<img src="<?= $projects->url() ?>" alt="Thumbnail for <?= $projects->title() ?>" />
		</a>
	</div>
	<div class="col12 col4--md">
		<a href="<?= $projects->url() ?>" class="col6">
			<img src="<?= $projects->url() ?>" alt="Thumbnail for <?= $projects->title() ?>" />
		</a>
		<a href="<?= $projects->url() ?>" class="col6">
			<img src="<?= $projects->url() ?>" alt="Thumbnail for <?= $projects->title() ?>" />
		</a>
	</div>
	<div class="col12 col4--md">
		<a href="<?= $projects->url() ?>" class="col12">
			<img src="<?= $projects->url() ?>" alt="Thumbnail for <?= $projects->title() ?>" />
		</a>
		<a href="<?= $projects->url() ?>" class="col12">
			<img src="<?= $projects->url() ?>" alt="Thumbnail for <?= $projects->title() ?>" />
		</a>
	</div>
</div>
<!-- END: showcase-projects -->

Why not a foreach loop? If you add ->limit(3) to the end of your chain, you have three random projects, without repeating your HTML.

So the first and last column will hold 2 full width divs, while the middle column will hold 2 split divs vertical basically creating something like this = | | =

If I was to use a foreach loop for all three columns - won’t I run into it possibly duplicating what is shown on the page?

Hm, another option is to use $projects->nth(0), $projects->nth(1) and $projects->nth(2). (->nth() starts at 0.)

Still feels like repeating yourself, though.

Hmmm, not sure I understand the ->nth() method.

Maybe the easiest solution here is for me to re-visit the HTML structure and just use JS to sort and order the elements…

It is just returning a single page object, the 0th, the 1st, the 2nd, etc. of your shuffled Pages collection.

<div class="container-fluid">
	<div class="col12 col4--md">
		<a href="<?= $projects->nth(0)->url() ?>" class="col12">
			<img src="<?= $projects->nth(0)->url() ?>" alt="Thumbnail for <?= $projects->nth(0)->title() ?>" />
		</a>
		<a href="<?= $projects->nth(1)->url() ?>" class="col12">
			<img src="<?= $projects->nth(1)->url() ?>" alt="Thumbnail for <?= $projects->nth(1)->title() ?>" />
		</a>
	</div>

I mean it’s ugly but it’s no foreach :wink:

1 Like

Ah right I see, this helps me for what I want to achieve.

For now cleanleness doesn’t really bother me as I am just learning the CMS, and PHP for that matter. My intent is to build everything I want and then pay someone to analyse, report and help me clean up code to a standard etc…

Thanks for the help. I can’t get over how helpful some of the guys on this forum are, and at times I feel like I’m just sponging for answers, so when I can I hope to give back to the community :slight_smile:

3 Likes

First version, with a count helper and using the modulo operator:

<?php $projects = page('projects')->children()->visible()->shuffle()->limit(6);  ?>
<div class="container-fluid">
   <?php $count=1; foreach($projects as $project): ?>
     <?php if($count % 2 != 0): ?>
      <div class="col12 col4--md">
      <?php endif ?>
		<a href="<?= $project->url() ?>" class="<?php e(($count == 3 || $count == 4),'col6', 'col12') ?>">
			<img src="<?= $project->url() ?>" alt="Thumbnail for <?= $project->title() ?>" />
		</a>
    <?php if($count%2 == 0): ?>
    </div>
     <?php endif ?>
   <?php $count++; endforeach ?>
</div>

(note that the project url in the image src does not really make sense, not sure what you want to get here, maybe the first image?)

Or better using the chunk() method that is ideal for this kind of “bootstrap row stuff”:

<?php 
$projects = page('projects')->children()->visible()->shuffle()->limit(6);
// create chunks of the same size
// result is a nested collection object
$chunks = $projects->chunk(2);
?>
<div class="container-fluid">

  <?php 
  // loop through "outer" collection
  foreach($chunks as $items): ?>
    <div class="col12 col4--md">
      <?php
      //loop through nested collection
      foreach($items as $project): ?>
        <a href="<?= $project->url() ?>" class="<?php e(($chunks->indexOf($items) == 1),'col6', 'col12') ?>">
          <img src="<?= $project->url() ?>" alt="Thumbnail for <?= $project->title() ?>" />
        </a>
      <?php endforeach; ?>
    </div>
  <?php endforeach ?>
</div>
2 Likes

texnixe - Many thanks. So I was playing around with the chunk method, but your example is only outputting 1 item get column. I would like to items per column. I’ve changed the chunk size and it ends only only outputting 2 columns and not 3.

Reading the page about chunks() I copied their example and it outs 2 rows each with 4 items using chunk(4).

Can you guide me as to what needs changing to output 2 items per column - the output I am getting at the moment is this

<div class="container-fluid">
  <div class="col12 col4--md">
    <a href="http://localhost/kirby-dev/projects/project-b" class="col12">
      <img src="http://localhost/kirby-dev/content/1-projects/2-project-b/room.jpg" alt="Thumbnail for Project B"/>
    </a>
  </div>
  <div class="col12 col4--md">
    <a href="http://localhost/kirby-dev/projects/project-d" class="col6">
      <img src="http://localhost/kirby-dev/content/1-projects/4-project-d/letters.jpg" alt="Thumbnail for Project D"/>
    </a>
  </div>
  <div class="col12 col4--md">
    <a href="http://localhost/kirby-dev/projects/project-e" class="col12">
      <img src="http://localhost/kirby-dev/content/1-projects/5-project-e/typewriter.jpg" alt="Thumbnail for Project E"/>
    </a>
  </div>
</div>

With regards to the image URL I know it’s broken in the code I posted and I will be using this

<?php if($image = $items->images()->sortBy('sort', 'asc')->first()): ?>
  <img src="<?= $image->url() ?>" alt="Thumbnail for <?= $project->title() ?>"/>
<?php endif ?>

That is strange, because I tested the code before posting here and this is what I get:

<div class="container-fluid">
        <div class="col12 col4--md">
              <a href="http://localhost/k253/content/1-projects/1-project-a/closeup.jpg" class="col12">
          <img src="http://localhost/k253/content/1-projects/1-project-a/closeup.jpg" alt="Thumbnail for ">
        </a>
              <a href="http://localhost/k253/content/1-projects/1-project-a/creative-tools.jpg" class="col12">
          <img src="http://localhost/k253/content/1-projects/1-project-a/creative-tools.jpg" alt="Thumbnail for ">
        </a>
          </div>
      <div class="col12 col4--md">
              <a href="http://localhost/k253/content/1-projects/1-project-a/folding-rule.jpg" class="col6">
          <img src="http://localhost/k253/content/1-projects/1-project-a/folding-rule.jpg" alt="Thumbnail for ">
        </a>
              <a href="http://localhost/k253/content/1-projects/2-project-b/room.jpg" class="col6">
          <img src="http://localhost/k253/content/1-projects/2-project-b/room.jpg" alt="Thumbnail for ">
        </a>
          </div>
      <div class="col12 col4--md">
              <a href="http://localhost/k253/content/1-projects/2-project-b/table.jpg" class="col12">
          <img src="http://localhost/k253/content/1-projects/2-project-b/table.jpg" alt="Thumbnail for ">
        </a>
              <a href="http://localhost/k253/content/1-projects/3-project-c/camera.jpg" class="col12">
          <img src="http://localhost/k253/content/1-projects/3-project-c/camera.jpg" alt="Thumbnail for ">
        </a>
          </div>
  </div>

Using this code in a starter kit:

<?php
$images = page('projects')->children()->images()->limit(6);
$chunks = $images->chunk(2);

?>

<div class="container-fluid">
  <?php $count=1; ?>
  <?php foreach($chunks as $items): ?>
    <div class="col12 col4--md">
      <?php foreach($items as $image): ?>
        <a href="<?= $image->url() ?>" class="<?php e(($chunks->indexOf($items) == 1),'col6', 'col12') ?>">
          <img src="<?= $image->url() ?>" alt="Thumbnail for <?= $image->title() ?>" />
        </a>
      <?php endforeach; ?>
    </div>
  <?php endforeach ?>
</div>

(note that I only used images in this example, but it is just an example).

1 Like

I spotted the mistake

I used

<?php if($image = $items->images()->sortBy('sort', 'asc')->first()): ?>

and not

<?php if($image = $project->images()->sortBy('sort', 'asc')->first()): ?>

Many thanks for the help as always. Time to read up the documentation some more about chunks to understand it deeper.

I think you will get an understanding of chunks if you do a var_dump($chunks) to see the structure of the nested collection.