1

Let's say I have a child of a parent collection and I want to know who the next sibling is. My parent collection is ordered differently than internal id so I can't use the method described here:

Laravel previous and next records

Which would work except I'm sorting by name and time, not internal id. I'm hoping that there's a way to just get the parent collection, find this child's position within it, and then look forward or back within that collection to get next or previous.

Edit:

So, I made this, which works, but seems clunky. Is there a more efficient way to do this?

public function next()
{
    $previous = null;
    foreach ($this->album->media as $media)
    {
        if(!empty($previous && $previous->id == $this->id))
        {
            // Yay! Our current record  is the 'next' record.
            return $media->id;
        }
        $previous = $media;
    }
    return null;
}

public function previous()
{
    $previous = null;
    foreach ($this->album->media as $media)
    {
        if(!empty($previous && $media->id == $this->id))
        {
            // Yay! Our previous record is the 'previous' record.
            return $previous;
        }
        $previous = $media->id;
    }
    return null;
}
Community
  • 1
  • 1
Citizen
  • 12,430
  • 26
  • 76
  • 117
  • you could, by extending the queries of the given example by the sort condition. how is your collection sorted? You would need a sort a orderBy Condition which basically does not change the original order. if you provide that, im sure we can help – nozzleman Feb 20 '15 at 09:19
  • @nozzleman By time, and for duplicate times, by alphabetical name. – Citizen Feb 20 '15 at 15:23
  • okay, i guess with double order-condition you already found a good solution. other solutions would include db-server-specific stuff like row numbers i guess. – nozzleman Feb 20 '15 at 17:00
  • Why do not you just use `paginate(1)` for that? – Anatoliy Arkhipov Mar 07 '15 at 05:10
  • It's not paginated by key. – Citizen Mar 07 '15 at 05:16

3 Answers3

3

You should never load the entire table to loop through it to find the next/previous item, instead do it this way:

$next = $this->album->media()->orderBy('id')->where('id', '>', $this->id)->first();
Leo Silver
  • 51
  • 6
2

Here is the simple line of code

// next
function next($product_id)
{
  $next = Product::where('id', '>', $product_id)->first();
  return $next;
}

// previous
function previous($product_id)
{
  $previous = Product::where('id', '<', $product_id)->first();
  return $previous;
}
Pri Nce
  • 576
  • 6
  • 18
0

This did the trick:

public function next()
{
    $previous = null;
    foreach ($this->album->media as $media)
    {
        if(!empty($previous && $previous->id == $this->id))
        {
            // Yay! Our current record  is the 'next' record.
            return $media->id;
        }
        $previous = $media;
    }
    return null;
}

public function previous()
{
    $previous = null;
    foreach ($this->album->media as $media)
    {
        if(!empty($previous && $media->id == $this->id))
        {
            // Yay! Our previous record is the 'previous' record.
            return $previous;
        }
        $previous = $media->id;
    }
    return null;
}
Citizen
  • 12,430
  • 26
  • 76
  • 117