Collection::sort

Orders a collection by its values, keeping every item's original key.

Signature
Collection::sort(callable|int|null $callback = null): static

Parameters

ParameterTypeDescription
$$callbackoptionalcallable|int|null= nullA comparator invoked as ($a, $b) returning a negative number, zero or a positive number, or one of PHP's sort flags such as SORT_STRING or SORT_NATURAL. Null sorts with the default comparison.

Return value

staticA new collection with the items ordered by value and their original keys preserved.

Sorting compares the values and drags the keys along with them. A list sorted from [5, 3, 1, 2, 4] comes back keyed 2, 3, 1, 4, 0, which is correct but ruins any assumption that a collection is a list. Chain values() before json_encode(), before toArray() on an API response, and before indexing by position — this is by far the most common bug on this method.

The argument is overloaded. Pass a comparator and it runs uasort(); pass an integer sort flag and it runs asort() with that flag. That is why sort(SORT_STRING) and sort(fn ($a, $b) => ...) both work. PHP 8's sorts are stable, so items that compare equal keep their original relative order.

Reach for it on flat collections of scalars. For arrays or objects, comparing them directly is meaningless — use sortBy() with a key or a closure instead. sortDesc() is the descending twin.

Note that the default comparison is PHP's <=>, so mixed types sort by PHP's own rules and numeric strings compare numerically.

Example

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

When to use it

  • Order a list of numeric scores or prices before rendering a table.
  • Alphabetize a flat array of tag names pulled from several sources.
  • Sort version-like strings naturally with sort(SORT_NATURAL).

Frequently asked questions

Why are my array keys scrambled after sorting?

They are not scrambled — sort() preserves each item's original key while reordering the values, so the keys end up out of sequence. Chain values() to renumber them from zero.

How do I sort a collection of arrays or models?

Use sortBy() with a key, a dot path or a closure, because sort() compares whole arrays or objects and gives meaningless results. sortByDesc() covers the descending case.

Can I pass a sort flag instead of a callback?

Yes — sort(SORT_STRING) or sort(SORT_NATURAL) runs asort() with that flag. Anything callable is treated as a comparator and runs uasort() instead.

More examples

Sort flags versus the default comparison

Prints [1,2,9,10], then [1,10,2,9] under string comparison. The version strings sort to [v1.10, v1.2, v1.9] by default and [v1.2, v1.9, v1.10] with SORT_NATURAL — the flag form is the fix for anything that ends in a number.

Example · php
<?php

$mixed = collect([10, 9, 2, 1]);

// Default: numeric comparison.
print_r($mixed->sort()->values()->all());

// SORT_STRING compares them as text.
print_r($mixed->sort(SORT_STRING)->values()->all());

$versions = collect(['v1.10', 'v1.9', 'v1.2']);

print_r($versions->sort()->values()->all());
print_r($versions->sort(SORT_NATURAL)->values()->all());

Stability and equal elements

Prints [second, first, third]. PHP 8 sorts are stable, so 'first' and 'third' both have priority 2 and keep the order they were declared in. Relying on that is safe on PHP 8 and later, but was not before 8.0.

Example · php
<?php

$tasks = collect([
    'first'  => ['priority' => 2],
    'second' => ['priority' => 1],
    'third'  => ['priority' => 2],
]);

$ordered = $tasks->sort(
    fn (array $a, array $b) => $a['priority'] <=> $b['priority']
);

print_r($ordered->keys()->all());

Why sort() is wrong for rows

The first call compares the arrays themselves, which PHP does key by key, so the ordering depends on incidental structure rather than on price. sortBy('price') is the correct tool once the items stop being scalars.

Example · php
<?php

$rows = collect([
    ['name' => 'Desk', 'price' => 200],
    ['name' => 'Chair', 'price' => 100],
]);

// Comparing arrays element by element — almost never what you want.
print_r($rows->sort()->values()->all());

// Compare the field you actually care about.
print_r($rows->sortBy('price')->values()->all());

Discussion

  • Be the first to comment on this lesson.