Collection::values

Returns a new collection with the keys reset to consecutive integers from zero.

Signature
public function values(): static

Return value

static<int, TValue>A new collection with the same items in the same order, keyed 0 to n-1.

values is array_values on the backing array: same items, same order, keys thrown away and replaced with 0..n-1. It returns a new collection and never mutates the receiver.

Why you almost always need it

Most Collection methods preserve keys. filter, reject, where, whereIn, unique, sortBy, sort, shuffle and a negative take all return items still carrying their original indexes. That is invisible while the data stays in PHP, and breaks the moment it does not: json_encode renders an array as a JSON array only when the keys are exactly 0..n-1 in order, so a filtered collection serializes as {"0":…,"2":…} and the JavaScript on the other end gets an object where it expected a list.

The rule: values() is the last call before anything leaves PHP — toJson(), an API resource, a controller return, a Blade loop with $loop->index.

What trips people up

String keys are discarded too, so calling it on an associative collection loses the labels entirely — that is keys()/values() territory, not a mistake to make by reflex. And because it returns a new collection, forgetting to use the return value is a silent no-op.

Example

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

When to use it

  • Reindex a filtered collection so it JSON-encodes as an array
  • Reset keys after sortBy before returning a list from an API endpoint
  • Produce a zero-indexed list for a Blade loop that relies on $loop->index
  • Drop the keys of a groupBy result to get a flat list of groups

Frequently asked questions

How do I reset the keys of a Laravel collection to 0, 1, 2?

Call ->values(), which returns a new collection with the same items reindexed from zero. It is the collection equivalent of array_values and does not modify the original.

Why do I need values() after filter() in Laravel?

filter preserves the source keys, so the surviving items keep gaps like 0, 2, 3 — and json_encode only renders a PHP array as a JSON array when the keys are exactly 0..n-1 in order. Without values() the response is a JSON object.

Does values() modify the original collection?

No. It returns a new collection, so you must use the return value — calling $collection->values() and discarding the result changes nothing.

More examples

The methods that make values() necessary

sort() is the most deceptive of these: no items were removed, so the collection looks intact, but the keys are now out of order and json_encode demands 0..n-1 in sequence. reverse() has the same effect. A single values() before serializing covers every one of these cases.

Example · php
<?php

$words = collect(['pear', 'fig', 'apple', 'date']);

foreach (['sort', 'shuffle'] as $ignored) {}

echo $words->filter(fn ($w) => strlen($w) > 3)->toJson(), "\n";
echo $words->reject(fn ($w) => strlen($w) > 3)->toJson(), "\n";
echo $words->sort()->toJson(), "\n";
echo $words->unique()->reverse()->toJson(), "\n";

// One values() at the end of each fixes them all.
echo $words->sort()->values()->toJson(), "\n";

// Output:
// {"0":"pear","2":"apple","3":"date"}
// {"1":"fig"}
// {"2":"apple","3":"date","1":"fig","0":"pear"}
// {"3":"date","2":"apple","1":"fig","0":"pear"}
// ["apple","date","fig","pear"]

In an API controller

get() returns models keyed by position, filter drops some of those keys and sortByDesc reorders what is left, so the response body would be {"3":{...},"0":{...}} rather than a JSON array. values() is the whole fix, and it belongs at the very end of the chain. Needs a booted application with a database.

Example · php
<?php

namespace App\Http\Controllers;

use App\Models\Order;

class OrderController extends Controller
{
    public function index()
    {
        return Order::with('lines')
            ->get()
            ->filter(fn (Order $o) => $o->total() > 0)
            ->sortByDesc('created_at')
            ->values();   // without this the client receives an object
    }
}

When values() is the wrong reflex

The first line is a correct JSON object keyed by region. Adding values() out of habit strips the region names and leaves two bare numbers with no way to tell which is which. Reach for values() when the keys are leftover positions, not when they carry meaning.

Example · php
<?php

$byRegion = collect([
    ['region' => 'north', 'amount' => 120],
    ['region' => 'south', 'amount' => 80],
    ['region' => 'north', 'amount' => 45],
])->groupBy('region');

// Keys here are meaningful data, not accidental indexes.
echo $byRegion->map->count()->toJson(), "\n";
echo $byRegion->map->count()->values()->toJson(), "\n";

// Output:
// {"north":2,"south":1}
// [2,1]

Discussion

  • Be the first to comment on this lesson.