Altering the first and last in a for each loop

Hey everyone!

I’m developing a site that has multiple sections, and I need to make an alteration to the first and last section of a foreach loop.

I followed the cookbook here and have this:

<div class="main-content">
  <?php if ($projects = page('projects')) : ?>
    <?php $first = $projects->first(); ?>
    <?php foreach ($projects->children()->listed() as $project) : ?>
      <?php if ($project = =$first) : ?>
        <?php snippet('firstAlbum', [
          'project' => $project
        ]) ?>
      <?php else : ?>
        <?php snippet('album', [
          'project' => $project
        ]) ?>
      <?php endif ?>
    <?php endforeach ?>
    <?php endif ?>
</div>

Where I’m creating a variable that is equal to the first project in the loop, and testing if the project being looped over is that one. However, this doesn’t work, it just treats the project as if it is not the first and uses the album template. While I know this question has been asked before here the eventual solution was a bit hacky, and I’m curious as to why the solution in the docs doesn’t work.

Thanks in advance!

Hi there,
there are few small errors, i think it should look like this:

<?php $projects = page('projects')->children()->listed(); ?>
  <?php if ($projects->isNotEmpty()): ?>
    <?php $first = $projects->first(); ?>
    <?php $last = $projects->last(); ?>
    <?php foreach ($projects as $project) : ?>
      <?php if ($project == $first) : ?>
        <?php snippet('firstAlbum', [
          'project' => $project
        ]) ?>
      <?php elseif ($project == $last) : ?>
        <?php snippet('lastAlbum', [
          'project' => $project
        ]) ?>
      <?php else: ?>
        <?php snippet('album', [
          'project' => $project
        ]) ?>
      <?php endif ?>
    <?php endforeach ?>
    <?php endif ?>

You can simplify the code a little maore, but this should work

cheers
tom

Wow! Thanks a bunch for the solution. I’m a bit confused as to why one works and the other doesn’t, but I’m super grateful for the insight, as I’m pretty green at PHP.

With the first line, you only assign a page to the $projects variable. In the second line, you call the method first() on that variable. But first() is a collection method, a single page cannot have first page. That’s why it doesn’t work.

To be 100% on the safe side, this would actually also need an if statement, to be sure you have a page object before calling the children :

<?php if ( $p = page('projects') ) : ?>
<?php $projects = $p->children()->listed(); ?>
<?php // rest of code ?>
<?php endif; ?>

I know this isn’t about your (solved) problem.
But why do you use so many php-tags?

It’s much easier to read when you put the code like that:

<?php 
   if ($projects = page('projects'))
   {
       $first = $projects->first();
       foreach ($projects->children()->listed() as $project)
       {
           if ($project == $first) 
           {
               snippet('firstAlbum', [ 
                     'project' => $project
               ]);
           }
           else
           {
               snippet('album', [
                 'project' => $project
               ]);
           }
       }
   }
?>