Currently Available: Need a skilled Software Developer for your next project?
Categories
Laravel

Sorting Laravel Collections by Nested Values

In Laravel, a collection holds items and provides methods for working with them. To sort items by a value inside a nested array or object, use sortBy() for ascending order or sortByDesc() for descending order. Use sort() to compare the items themselves or to define how Laravel compares them.

A nested value is a field stored inside another field, such as score inside stats. Laravel’s collection methods accept a dotted path, which names each field from the outside in. For example, stats.score selects the score field inside stats, so you can sort by that value without writing a comparison callback. These methods keep the items’ existing keys. Chain values() when you need new, sequential numeric keys.

Choose the method that matches the value you compare

sort() orders the items themselves. It works directly with values such as numbers and strings that Laravel can compare. To define a custom comparison, pass a callback, a function Laravel calls with two items. The callback returns a negative number, zero, or a positive number to show which item comes first.

$numbers = collect([5, 3, 1, 2, 4]);

$ascending = $numbers->sort();

The callback passed to sort() compares two items. This example sorts task arrays by their nested scores:

$byScore = $tasks->sort(
    fn (array $a, array $b) =>
        data_get($a, 'stats.score')  data_get($b, 'stats.score')
);

The <=> operator compares the two score values and returns a negative number, zero, or a positive number. For a simple sort by one field, sortBy() takes less code. Laravel’s collection documentation says that sort() sorts item values and keeps their original keys.

sortBy() selects a value from each item and sorts by that value in ascending order. Pass a field name or dotted path; a callback can also return the value to sort by.

$tasks = collect([
    ['id' => 41, 'owner' => ['name' => 'Zoe'],  'stats' => ['score' => 7]],
    ['id' => 17, 'owner' => ['name' => 'Amir'], 'stats' => ['score' => 9]],
    ['id' => 28, 'owner' => ['name' => 'Mina'], 'stats' => ['score' => 5]],
]);

$byOwner = $tasks->sortBy('owner.name');
$lowestScoresFirst = $tasks->sortBy('stats.score');

Here, owner.name means the name field inside owner. Laravel also provides sortByDesc() with the same kind of argument, but in descending order:

$highestScoresFirst = $tasks->sortByDesc('stats.score');

A sortBy() callback receives one item and returns the value Laravel should use to sort it. A sort() callback instead compares two items. Laravel’s data_get helper reads a value from a nested array or object using a dotted path. It also accepts a fallback value to use when the path is missing:

$byScore = $tasks->sortBy(
    fn (array $task) => data_get($task, 'stats.score', 0)
);

When stats.score is missing, the task gets a sort value of 0. Choose a fallback that fits your data and the order you want. Laravel explains nested paths and fallback values in its data_get helper documentation.

Preserve keys or create a sequential list

Laravel’s sorting methods retain each item’s original key. Laravel keeps each ID attached to its item when it sorts a collection keyed by IDs:

$tasksById = collect([
    41 => ['owner' => ['name' => 'Zoe']],
    17 => ['owner' => ['name' => 'Amir']],
    28 => ['owner' => ['name' => 'Mina']],
]);

$sortedByOwner = $tasksById->sortBy('owner.name');

The sorted collection still uses keys 41, 17, and 28, though the items appear in a different order. Numeric keys can then have gaps or no longer match the items’ positions. To create a list with zero-based, sequential keys, chain values():

$sortedList = $tasks
    ->sortBy('owner.name')
    ->values();

Sorting item values does not sort the collection’s keys. If you need to order by the keys themselves, use a key-sorting method such as sortKeys().

Handle ties and missing values explicitly

When two items have the same sort value, add a tie-breaker if their order matters. Laravel documents sorting by multiple attributes with sortBy(). An explicit secondary comparison shows which item should come first. Do not assume tied items keep their previous order unless you know that behavior is guaranteed for your case.

Decide how to sort items with missing nested values. Use a callback with data_get to assign a fallback, or define another way to compare those items. The right fallback depends on your data and the order you want.

What I'm building

Delegate tasks. Get software.

Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.

Take a look at vroni.com

Email updates

Usually a new article and a few links I found interesting.

No spam. Unsubscribe with one click.

Leave a Reply

Your email address will not be published. Required fields are marked *