Get previous and next items in collection, if they exist

Hi,

I have a collection of users, which I have filtered and sorted how I need.

I now need to get a specific user from this list (the currently logged in user), and output some info alongside their position in the list. I also need to find the entries immediately before and immediately after that user, and output data from them too.

The only only exception to this is if the logged in user is either first or last in the collection, in which case I need to output the next two or previous two users.

For example, if the collection looks like this:

  • Arthur
  • Zaphod
  • CurrentUser
  • Trillian
  • Ford

I need to output:

  • 2nd: Zaphod
  • 3rd: CurrentUser
  • 4th: Trillian

But if it looks like this:

  • CurrentUser
  • Arthur
  • Zaphod
  • Trillian
  • Ford

I need to output:

  • 1st: CurrentUser
  • 2nd: Arthur
  • 3rd: Zaphod

Hopefully this makes sense. I am getting the current user and their position like this at the moment:

<?php if($kirby->user(): ?>
<?php foreach($usersCollection as $person): ?>
  <?php if($person->id() == $kirby->user()->id()): ?>
    <?php
      $locale = 'en_GB';
      $nf = new NumberFormatter($locale, NumberFormatter::ORDINAL);
    ?>
    <?= $nf->format($person->indexOf($usersCollection) + 1) ?>:
    <?= $person->username() ?>
  <?php endif ?>
<?php endforeach ?>
<?php endif ?>

This might not be the best way! But I am stuck with how to get the entries before and after. I think I can manage if the user is first or last.

If anyone has any pointers or thoughts that would be awesome.

First of all, instead of looping through, you can use findBy() to get the current user element from the collection (not tested for syntax errors)

$user = $usersCollection->findBy('id', $kirby->user()->id();

if ($user->hasPrev($usersCollection) {
  $prevUser = $user->prev();
}

if ($user->hasNext($usersCollection) {
  $nextUser = $user->next();
}

if ($user->hasPrev($usersCollection) === false and $nextUser?->hasNext(usersCollection)) {
  $lastUser = $nextUser->next();
}

Hi Sonja,

Thanks for the quick reply. I did use findBy() at first, but couldn’t work out a way of getting their position when I used that (e.g. 4th: Username). Is there a way of getting that?

The rest of your reply looks great, I hadn’t thought about hasPrev and hasNext they will be ideal for getting the other listings I need, as long as I can get the positions in this way as well

You can get the position with this code for each of $user, $prevUser, etc.