27

I have a laravel collection object.

I want to use the nth model within it.

How do I access it?

Edit:

I cannot find a suitable method in the laravel documentation. I could iterate the collection in a foreach loop and break when the nth item is found:

foreach($collection as $key => $object)
{
    if($key == $nth) {break;}
}
// $object is now the nth one

But this seems messy.

A cleaner way would be to perform the above loop once and create a simple array containing all the objects in the collection. But this seems like unnecessary duplication.

In the laravel collection class documentation, there is a fetch method but I think this fetches an object from the collection matching a primary key, rather than the nth one in the collection.

Chris
  • 54,599
  • 30
  • 149
  • 186
theHands
  • 373
  • 1
  • 3
  • 8
  • [Sharing your research helps everyone](http://meta.programmers.stackexchange.com/questions/6559/why-is-research-important). Tell us what you've tried and why it didn’t meet your needs. This demonstrates that you’ve taken the time to try to help yourself, it saves us from reiterating obvious answers, and most of all it helps you get a more specific and relevant answer. Also see [ask] – gnat Jun 26 '14 at 11:12
  • 3
    Fair enough. Question edited. – theHands Jun 26 '14 at 13:29

4 Answers4

57

Seeing as Illuminate\Support\Collection implements ArrayAccess, you should be able to simply use square-bracket notation, ie

$collection[$nth]

This calls offsetGet internally which you can also use

$collection->offsetGet($nth)

and finally, you can use the get method which allows for an optional default value

$collection->get($nth)
// or
$collection->get($nth, 'some default value')
Phil
  • 157,677
  • 23
  • 242
  • 245
14

@Phil's answer doesn't quite obtain the nth element, since the keys may be unordered. If you've got an eloquent collection from a db query it'll work fine, but if your keys aren't sequential then you'll need to do something different.

$collection = collect([0 => 'bish', 2 => 'bash']); $collection[1] // Undefined index

Instead we can do $collection->values()[1] // string(4) bash which uses array_values()

Or even make a macro to do this:

Collection::macro('nthElement', function($offset, $default = null) {
    return $this->values()->get($offset, $default);
}):

Example macro usage:

$collection = collect([0 => 'bish', 2 => 'bash']);
$collection->nthElement(1) // string(4) 'bash'
$collection->nthElement(3) // undefined index
$collection->nthElement(3, 'bosh') // string (4) bosh
Harry
  • 2,429
  • 4
  • 21
  • 26
6

I am late to this question, but I thought this might be a useful solution for someone.

Collections have the slice method with the following parameters:

 $items->slice(whereToStartSlice, sizeOfSlice);

Therefore, if you set the whereToStartSlice parameter at the nth item and the sizeOfSlice to 1 you retrieve the nth item.

Example:

 $nthItem = $items->slice($nth,1);
Lew Perren
  • 1,209
  • 1
  • 10
  • 14
  • best answer for me as I'm working with a key-value pair collection – Jacobski Dec 09 '21 at 00:38
  • Very handy if you want to grab first n items from the collection. You simply set `offset` to `0` and `limit` to the quantity you want. eg: `$reviews->slice(0, 10)` // first 10 reviews – Matt Komarnicki Jul 07 '23 at 21:00
2

If you are having problems with the collection keeping the indices after sorting... you can make a new collection out of the values of that collection and try accessing the newly indexed collection like you would expect:

e.g. Get the second highest priced item in a collection

$items = collect(
                 [
                  "1" => ["name" => "baseball", "price" => 5],
                  "2" => ["name"=> "bat", "price" => 15],
                  "3" => ["name" => "glove", "price" => 10]
                 ]
                );

collect($items->sortByDesc("price")->values())[1]["name"];

// Result: glove

Similar to morphs answer but not the same. Simply using values() after a sort will not give you the expected results because the indices remain coupled to each item.

Credit to @howtomakeaturn for this solution on the Laravel Github: https://github.com/laravel/framework/issues/1335

Noah Gary
  • 916
  • 12
  • 25