Collection::slice

Extracts a portion of a collection starting at a given index, optionally limited in length.

Signature
Collection::slice(int $offset, ?int $length = null): static

Parameters

ParameterTypeDescription
$$offsetintWhere the slice starts. A negative offset counts back from the end of the collection.
$$lengthoptionalint|null= nullHow many items to take. Null takes everything to the end; a negative length stops that many items before the end.

Return value

staticA new collection containing the requested portion of the items, with their original keys preserved.

A thin wrapper around array_slice() with key preservation forced on. That last detail is the whole story: slice(4, 2) on a list returns items keyed 4 and 5, not 0 and 1. Everything reads correctly until you json_encode() the result and get an object, or index [0] and get null. Chain values() whenever the slice is handed to anything that expects a list.

Both arguments accept negatives, which is what makes the method worth reaching for over skip()/take(). A negative offset counts from the end — slice(-3) is the last three items — and a negative length stops short of the end, so slice(1, -1) trims the first and last item in one call.

Use it for fixed windows: a top-three podium after sorting, the last few log lines, a preview of a longer list. If the offset counts from the front and you also want a limit, skip()->take() often reads better even though it does the same thing.

Offsets past the end yield an empty collection rather than an error.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Show the top three entries of a leaderboard after sorting it.
  • Grab the last twenty lines of an in-memory log buffer.
  • Trim the first and last elements off a parsed path with slice(1, -1).

Frequently asked questions

Does slice reindex the keys?

No — keys are always preserved, so slice(4, 2) returns items still keyed 4 and 5. Chain values() to renumber them from zero.

How do I get the last N items of a collection?

Pass a negative offset: slice(-3) returns the final three items. take(-3) does the same thing, and both preserve keys.

What is the difference between slice and skip?

skip($n) is literally slice($n) with no length, so they behave identically for that case. Use slice when you also need a length or a negative offset.

More examples

Negative lengths and out-of-range offsets

The first prints [var, www, html]: a negative length stops that many items before the end. slice(99) gives array(0) {} rather than throwing, and an over-long length is clamped, printing [html, index.php].

Example · php
<?php

$path = collect(['', 'var', 'www', 'html', 'index.php']);

// Drop the first and the last segment in one call.
print_r($path->slice(1, -1)->values()->all());

// Past the end is empty, not an error.
var_dump($path->slice(99)->all());

// A length longer than what remains is simply truncated.
print_r($path->slice(3, 100)->values()->all());

A podium from a sorted collection

Prints 1. Linus (94), 2. Grace (88), 3. Ada (71). values() is called before slice, not after, so the keys are already 0, 1, 2 and can be used directly as podium positions — slicing a sortBy result without it would give positions 2, 3, 1.

Example · php
<?php

$scores = collect([
    ['player' => 'Ada',   'points' => 71],
    ['player' => 'Linus', 'points' => 94],
    ['player' => 'Grace', 'points' => 88],
    ['player' => 'Alan',  'points' => 62],
]);

$podium = $scores->sortByDesc('points')->values()->slice(0, 3);

foreach ($podium as $position => $row) {
    echo ($position + 1) . ". {$row['player']} ({$row['points']})" . PHP_EOL;
}

In an application: a preview list with a remainder count

A common 'Ada, Linus and 12 others' pattern. slice(0, 5) is safe on a collection with fewer than five attendees — it simply returns what exists — and max(0, ...) keeps the remainder from going negative.

Example · php
<?php

namespace App\Http\Controllers;

use App\Models\Attendee;

class EventController extends Controller
{
    public function show(int $eventId)
    {
        $attendees = Attendee::forEvent($eventId)->get();

        return view('event', [
            'preview' => $attendees->slice(0, 5)->values(),
            'more' => max(0, $attendees->count() - 5),
        ]);
    }
}

Discussion

  • Be the first to comment on this lesson.